Draft implementation

This commit is contained in:
Victor Shcherb 2011-10-19 14:50:16 +02:00
parent cfa7138ed0
commit 93098a731f
12 changed files with 550 additions and 1017 deletions

View file

@ -36,7 +36,6 @@ public class MapRenderingTypes {
private static final Log log = LogUtil.getLog(MapRenderingTypes.class); private static final Log log = LogUtil.getLog(MapRenderingTypes.class);
// TODO Internet access bits for point, polygon
/** standard schema : /** standard schema :
polygon : ll aaaaa ttttt 11 : 14 bits polygon : ll aaaaa ttttt 11 : 14 bits
multi : ll aaaaa ttttt 00 : 14 bits multi : ll aaaaa ttttt 00 : 14 bits
@ -47,6 +46,7 @@ public class MapRenderingTypes {
t - object type, s - subtype t - object type, s - subtype
*/ */
// keep sync ! not change values
public final static int MULTY_POLYGON_TYPE = 0; public final static int MULTY_POLYGON_TYPE = 0;
public final static int POLYGON_TYPE = 3; public final static int POLYGON_TYPE = 3;
public final static int POLYLINE_TYPE = 2; public final static int POLYLINE_TYPE = 2;

View file

@ -15,8 +15,11 @@ public class RenderingRuleSearchRequest {
private List<RenderingRule> searchedScope = new ArrayList<RenderingRule>(); private List<RenderingRule> searchedScope = new ArrayList<RenderingRule>();
public final RenderingRuleStorageProperties ALL;
public RenderingRuleSearchRequest(RenderingRulesStorage storage) { public RenderingRuleSearchRequest(RenderingRulesStorage storage) {
this.storage = storage; this.storage = storage;
this.ALL = storage.PROPS;
props = storage.PROPS.getPoperties(); props = storage.PROPS.getPoperties();
values = new int[props.length]; values = new int[props.length];
for (int i = 0; i < props.length; i++) { for (int i = 0; i < props.length; i++) {
@ -55,6 +58,14 @@ public class RenderingRuleSearchRequest {
System.arraycopy(savedFvalues, 0, fvalues, 0, fvalues.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() { public boolean isFound() {
return searchedScope.size() > 0; return searchedScope.size() > 0;
} }
@ -174,4 +185,9 @@ public class RenderingRuleSearchRequest {
return values[property.getId()]; return values[property.getId()];
} }
public int getIntPropertyValue(RenderingRuleProperty property, int defValue) {
int val = values[property.getId()];
return val == -1 ? defValue : val;
}
} }

View file

@ -94,12 +94,13 @@ public class RenderingRuleStorageProperties {
R_MAXZOOM = registerRule(RenderingRuleProperty.createInputLessIntProperty(MAXZOOM)); R_MAXZOOM = registerRule(RenderingRuleProperty.createInputLessIntProperty(MAXZOOM));
R_NIGHT_MODE = registerRule(RenderingRuleProperty.createInputBooleanProperty(NIGHT_MODE)); R_NIGHT_MODE = registerRule(RenderingRuleProperty.createInputBooleanProperty(NIGHT_MODE));
R_LAYER = registerRule(RenderingRuleProperty.createInputIntProperty(LAYER)); R_LAYER = registerRule(RenderingRuleProperty.createInputIntProperty(LAYER));
R_ORDER_TYPE = registerRule(RenderingRuleProperty.createInputStringProperty(ORDER_TYPE)); R_ORDER_TYPE = registerRule(RenderingRuleProperty.createInputIntProperty(ORDER_TYPE));
R_TEXT_LENGTH = registerRule(RenderingRuleProperty.createInputIntProperty(TEXT_LENGTH));
R_REF = registerRule(RenderingRuleProperty.createInputBooleanProperty(REF));
// order - no sense to make it float // order - no sense to make it float
R_ORDER = registerRule(RenderingRuleProperty.createOutputIntProperty(ORDER)); R_ORDER = registerRule(RenderingRuleProperty.createOutputIntProperty(ORDER));
// text properties // text properties
R_TEXT_WRAP_WIDTH = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_WRAP_WIDTH)); R_TEXT_WRAP_WIDTH = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_WRAP_WIDTH));
R_TEXT_DY = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_DY)); R_TEXT_DY = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_DY));
@ -107,9 +108,8 @@ public class RenderingRuleStorageProperties {
R_TEXT_SIZE = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_SIZE)); R_TEXT_SIZE = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_SIZE));
R_TEXT_ORDER = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_ORDER)); R_TEXT_ORDER = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_ORDER));
R_TEXT_MIN_DISTANCE = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_MIN_DISTANCE)); R_TEXT_MIN_DISTANCE = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_MIN_DISTANCE));
R_TEXT_LENGTH = registerRule(RenderingRuleProperty.createOutputIntProperty(TEXT_LENGTH));
R_TEXT_SHIELD = registerRule(RenderingRuleProperty.createOutputStringProperty(TEXT_SHIELD)); R_TEXT_SHIELD = registerRule(RenderingRuleProperty.createOutputStringProperty(TEXT_SHIELD));
R_REF = registerRule(RenderingRuleProperty.createOutputStringProperty(REF));
R_TEXT_COLOR = registerRule(RenderingRuleProperty.createOutputColorProperty(TEXT_COLOR)); R_TEXT_COLOR = registerRule(RenderingRuleProperty.createOutputColorProperty(TEXT_COLOR));

View file

@ -17,6 +17,7 @@ import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParserFactory;
import net.osmand.LogUtil; import net.osmand.LogUtil;
import net.osmand.osm.MapRenderingTypes;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
@ -27,9 +28,10 @@ public class RenderingRulesStorage {
private final static Log log = LogUtil.getLog(RenderingRulesStorage.class); private final static Log log = LogUtil.getLog(RenderingRulesStorage.class);
public final static int POINT_RULES = 1; // keep sync !
public final static int LINE_RULES = 2; public final static int POINT_RULES = MapRenderingTypes.POINT_TYPE;
public final static int POLYGON_RULES = 3; 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 TEXT_RULES = 4;
public final static int ORDER_RULES = 5; public final static int ORDER_RULES = 5;
private final static int LENGTH_RULES = 6; private final static int LENGTH_RULES = 6;
@ -83,6 +85,10 @@ public class RenderingRulesStorage {
return bgNightColor; return bgNightColor;
} }
public int getBgColor(boolean nightMode){
return nightMode ? bgNightColor : bgColor;
}
public String getDepends() { public String getDepends() {
return depends; return depends;
} }
@ -107,6 +113,8 @@ public class RenderingRulesStorage {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void registerGlobalRule(RenderingRule rr, int state, Map<String, String> attrsMap) throws SAXException { private void registerGlobalRule(RenderingRule rr, int state, Map<String, String> attrsMap) throws SAXException {
int tag = rr.getIntPropertyValue(RenderingRuleStorageProperties.TAG); int tag = rr.getIntPropertyValue(RenderingRuleStorageProperties.TAG);
if(tag == -1){ if(tag == -1){
throw new SAXException("Attribute tag should be specified for root filter " + attrsMap.toString()); throw new SAXException("Attribute tag should be specified for root filter " + attrsMap.toString());
@ -168,8 +176,6 @@ public class RenderingRulesStorage {
this.parser = parser; this.parser = parser;
} }
@Override @Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
name = parser.isNamespaceAware() ? localName : name; name = parser.isNamespaceAware() ? localName : name;
@ -272,6 +278,12 @@ public class RenderingRulesStorage {
} }
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println(""+stack);
}
private Map<String, String> parseAttributes(Attributes attributes, Map<String, String> m) { private Map<String, String> parseAttributes(Attributes attributes, Map<String, String> m) {
for (int i = 0; i < attributes.getLength(); i++) { for (int i = 0; i < attributes.getLength(); i++) {
String name = parser.isNamespaceAware() ? attributes.getLocalName(i) : attributes.getQName(i); String name = parser.isNamespaceAware() ? attributes.getLocalName(i) : attributes.getQName(i);
@ -353,19 +365,19 @@ public class RenderingRulesStorage {
public static void main(String[] args) throws SAXException, IOException { public static void main(String[] args) throws SAXException, IOException {
RenderingRulesStorage storage = new RenderingRulesStorage(); RenderingRulesStorage storage = new RenderingRulesStorage();
storage.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream("new_default.render.xml")); storage.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream("new_default.render.xml"));
// storage.printDebug(TEXT_RULES, System.out); // storage.printDebug(POLYGON_RULES, System.out);
RenderingRuleSearchRequest searchRequest = new RenderingRuleSearchRequest(storage); RenderingRuleSearchRequest searchRequest = new RenderingRuleSearchRequest(storage);
searchRequest.setStringFilter(storage.PROPS.R_TAG, "highway"); searchRequest.setStringFilter(storage.PROPS.R_TAG, "landuse");
searchRequest.setStringFilter(storage.PROPS.R_VALUE, "motorway"); searchRequest.setStringFilter(storage.PROPS.R_VALUE, "grass");
searchRequest.setIntFilter(storage.PROPS.R_LAYER, 1); // searchRequest.setIntFilter(storage.PROPS.R_LAYER, 1);
searchRequest.setIntFilter(storage.PROPS.R_MINZOOM, 14); searchRequest.setIntFilter(storage.PROPS.R_MINZOOM, 17);
searchRequest.setIntFilter(storage.PROPS.R_MAXZOOM, 14); searchRequest.setIntFilter(storage.PROPS.R_MAXZOOM, 17);
searchRequest.setStringFilter(storage.PROPS.R_ORDER_TYPE, "line"); // searchRequest.setStringFilter(storage.PROPS.R_ORDER_TYPE, "line");
searchRequest.setBooleanFilter(storage.PROPS.R_NIGHT_MODE, true); // searchRequest.setBooleanFilter(storage.PROPS.R_NIGHT_MODE, true);
// searchRequest.setBooleanFilter(storage.PROPS.get("hmRendered"), true); // searchRequest.setBooleanFilter(storage.PROPS.get("hmRendered"), true);
searchRequest.search(LINE_RULES); searchRequest.search(POLYGON_RULES);
printResult(searchRequest, System.out); printResult(searchRequest, System.out);
} }

View file

@ -54,11 +54,14 @@
<!-- types : string, int, boolean; possibleValues comma separated possible values for int/string --> <!-- types : string, int, boolean; possibleValues comma separated possible values for int/string -->
<renderingProperty attr="hmRendered" name="All-Purpose Renderer" description="All-Purpose Renderer by Hardy" <renderingProperty attr="hmRendered" name="All-Purpose Renderer" description="All-Purpose Renderer by Hardy"
type="boolean" possibleValues=""/> type="boolean" possibleValues=""/>
<renderingProperty attr="appMode" name="Rendering mode" description="Select rendering specific mode"
type="string" possibleValues=",car,bicycle,pedestrian"/>
<!-- input exact layer, orderType check tag, value --> <!-- input exact layer, orderType check tag, value -->
<!-- point = 1, line = 2, polygon = 3 -->
<order> <order>
<!-- point has order 128 --> <!-- point has order 128 -->
<group orderType="polygon"> <group orderType="3">
<filter tag="building" value="" order="64" /> <filter tag="building" value="" order="64" />
<filter tag="building" value="" layer="-1" order="2" /> <filter tag="building" value="" layer="-1" order="2" />
@ -79,7 +82,7 @@
</group> </group>
<group orderType="line"> <group orderType="2">
<!-- Below see level --> <!-- Below see level -->
<filter tag="admin_level" value="0" order="0" /> <filter tag="admin_level" value="0" order="0" />
<filter tag="admin_level" value="1" order="0" /> <filter tag="admin_level" value="1" order="0" />
@ -120,14 +123,14 @@
<filter tag="highway" value="bridleway" order="35" /> <filter tag="highway" value="bridleway" order="35" />
</group> </group>
<filter tag="" value="" order="128" orderType="point"/> <filter tag="" value="" order="128" orderType="1"/>
<filter tag="" value="" layer="-1" order="1" orderType="polygon"/> <filter tag="" value="" layer="-1" order="1" orderType="3"/>
<filter tag="" value="" layer="1" order="64" orderType="polygon"/> <filter tag="" value="" layer="1" order="64" orderType="3"/>
<filter tag="" value="" order="1" orderType="polygon"/> <filter tag="" value="" order="1" orderType="3"/>
<filter tag="" value="" layer="-1" order="10" orderType="line"/> <filter tag="" value="" layer="-1" order="10" orderType="2"/>
<filter tag="" value="" layer="1" order="67" orderType="line"/> <filter tag="" value="" layer="1" order="67" orderType="2"/>
<filter tag="" value="" order="11" orderType="line"/> <filter tag="" value="" order="11" orderType="2"/>
</order> </order>
@ -135,7 +138,7 @@
<!-- PRIORITY Input to filter : tag, value, zoom [minzoom, maxzoom], textLength, ref, textOrder (default=20) --> <!-- PRIORITY Input to filter : tag, value, zoom [minzoom, maxzoom], textLength, ref, textOrder (default=20) -->
<text> <text>
<!-- Highway ref --> <!-- Highway ref -->
<filter minzoom="10" tag="highway" value="motorway" ref="only" textMinDistance="70" textColor="#ffffff" textSize="12" textBold="true" <filter minzoom="10" tag="highway" value="motorway" ref="true" textMinDistance="70" textColor="#ffffff" textSize="12" textBold="true"
textOrder="6"> textOrder="6">
<filter textLength="1" textShield="mot_shield1" /> <filter textLength="1" textShield="mot_shield1" />
<filter textLength="2" textShield="mot_shield2" /> <filter textLength="2" textShield="mot_shield2" />
@ -145,7 +148,7 @@
<filter textLength="6" textShield="mot_shield6" /> <filter textLength="6" textShield="mot_shield6" />
</filter> </filter>
<filter minzoom="10" tag="highway" value="trunk" ref="only" textMinDistance="70" textColor="#ffffff" textSize="12" textBold="true" <filter minzoom="10" tag="highway" value="trunk" ref="true" textMinDistance="70" textColor="#ffffff" textSize="12" textBold="true"
textOrder="6"> textOrder="6">
<filter textLength="1" textShield="tru_shield1" /> <filter textLength="1" textShield="tru_shield1" />
<filter textLength="2" textShield="tru_shield2" /> <filter textLength="2" textShield="tru_shield2" />
@ -155,7 +158,7 @@
<filter textLength="6" textShield="tru_shield6" /> <filter textLength="6" textShield="tru_shield6" />
</filter> </filter>
<filter minzoom="11" tag="highway" value="primary" ref="only" textMinDistance="70" textColor="#ffffff" textSize="12" <filter minzoom="11" tag="highway" value="primary" ref="true" textMinDistance="70" textColor="#ffffff" textSize="12"
textBold="true" textOrder="7"> textBold="true" textOrder="7">
<filter textLength="1" textShield="pri_shield1" /> <filter textLength="1" textShield="pri_shield1" />
<filter textLength="2" textShield="pri_shield2" /> <filter textLength="2" textShield="pri_shield2" />
@ -165,7 +168,7 @@
<filter textLength="6" textShield="pri_shield6" /> <filter textLength="6" textShield="pri_shield6" />
</filter> </filter>
<filter minzoom="13" tag="highway" value="secondary" ref="only" textMinDistance="70" textColor="#ffffff" textSize="12" <filter minzoom="13" tag="highway" value="secondary" ref="true" textMinDistance="70" textColor="#ffffff" textSize="12"
textBold="true" textOrder="8"> textBold="true" textOrder="8">
<filter textLength="1" textShield="sec_shield1" /> <filter textLength="1" textShield="sec_shield1" />
<filter textLength="2" textShield="sec_shield2" /> <filter textLength="2" textShield="sec_shield2" />
@ -175,7 +178,7 @@
<filter textLength="6" textShield="sec_shield6" /> <filter textLength="6" textShield="sec_shield6" />
</filter> </filter>
<filter minzoom="14" tag="highway" value="tertiary" ref="only" textMinDistance="70" textColor="#ffffff" textSize="12" <filter minzoom="14" tag="highway" value="tertiary" ref="true" textMinDistance="70" textColor="#ffffff" textSize="12"
textBold="true" textOrder="9"> textBold="true" textOrder="9">
<filter textLength="1" textShield="ter_shield1" /> <filter textLength="1" textShield="ter_shield1" />
<filter textLength="2" textShield="ter_shield2" /> <filter textLength="2" textShield="ter_shield2" />
@ -638,11 +641,12 @@
</groupFilter> </groupFilter>
</group> </group>
<!-- ZM 13 --> <group >
<group minzoom="14" strokeWidth_2="0.5" color_2="#b0b0b0" color="#ECECEC">
<filter tag="highway" value="service" /> <filter tag="highway" value="service" />
<filter tag="highway" value="pedestrian" /> <filter tag="highway" value="pedestrian" />
<filter tag="highway" value="footway" /> <filter tag="highway" value="footway" />
<groupFilter minzoom="14" strokeWidth_2="0.5" color_2="#b0b0b0" color="#ECECEC"/>
<groupFilter hmRendered="true" minzoom="13" strokeWidth_2="0.5" color_2="#b0b0b0" color="#ECECEC"/>
</group> </group>
<filter minzoom="11" tag="railway" value="station" color="#d4aaaa"> <filter minzoom="11" tag="railway" value="station" color="#d4aaaa">
@ -753,7 +757,7 @@
<!-- ZM 10 --> <!-- ZM 10 -->
<filter minzoom="9" shader="nr" color="#abdf96" tag="leisure" value="nature_reserve"> <filter minzoom="9" shader="nr" color="#abdf96" tag="leisure" value="nature_reserve">
<filter nightMode="true" shader="" color="#000034"> <filter nightMode="true" shader="" color="#000034" />
</filter> </filter>
<group> <group>
@ -889,8 +893,8 @@
</group> </group>
<filter minzoom="10" color="#a0ffa8a8" tag="landuse" value="military" /> <filter minzoom="10" color="#a0ffa8a8" tag="landuse" value="military">
<filter nightMode="true" color="#a0560000" > <filter nightMode="true" color="#a0560000" />
</filter> </filter>
@ -901,7 +905,7 @@
</filter> </filter>
<filter tag="landuse" value="wood" /> <filter tag="landuse" value="wood">
<filter hmRendered="true"> <filter hmRendered="true">
<filter minzoom="10" color="#aed1a0" /> <filter minzoom="10" color="#aed1a0" />
</filter> </filter>
@ -980,117 +984,92 @@
</groupFilter> </groupFilter>
</group> </group>
<!-- TODO START ->
<group> <group>
<filter tag="highway" value="tertiary" maxzoom="13" /> <filter tag="highway" value="tertiary" maxzoom="13" />
<filter tag="highway" value="tertiary_link" maxzoom="13" /> <filter tag="highway" value="tertiary_link" maxzoom="13" />
<filter color="#fefeb3" color_2="#fefeb3" shadowColor="#bababa" shadowRadius="1" > <groupFilter color="#fefeb3" color_2="#fefeb3" shadowColor="#bababa">
<filter minzoom="10" maxzoom="10" strokeWidth="3" /> <filter minzoom="10" maxzoom="10" strokeWidth="3" />
<filter minzoom="11" maxzoom="11" strokeWidth="4" /> <filter minzoom="11" maxzoom="11" strokeWidth="4" />
<filter minzoom="12" maxzoom="12" strokeWidth="5" /> <filter minzoom="12" maxzoom="12" strokeWidth="5" />
<filter minzoom="13" maxzoom="13" strokeWidth="6" /> <filter minzoom="13" maxzoom="13" strokeWidth="6" />
<switch> <!-- bridge -->
<case layer="-1" pathEffect="4_4" /> <filter layer="1" cap_2="SQUARE" color="#000000">
<case /> <!- all other cases ->
<filter>
<filter minzoom="14" maxzoom="14" strokeWidth="6" />
<filter minzoom="15" maxzoom="15" strokeWidth="8" />
<filter minzoom="16" maxzoom="16" strokeWidth="10" />
<!- radius 0 to avoid showing many black lines, but removed again due to bad visibility on some backgrounds ->
<filter minzoom="17" maxzoom="17" strokeWidth="13" />
<filter minzoom="18" strokeWidth="18" />
</filter>
</switch>
<!- bridge ->
<switch>
<case nightMode="false" color="#000000" />
<case nightMode="true" color="#ffffff" />
<filter layer="1" cap_2="SQUARE" >
<filter minzoom="13" maxzoom="14" strokeWidth="8" strokeWidth_2="6" /> <filter minzoom="13" maxzoom="14" strokeWidth="8" strokeWidth_2="6" />
<filter minzoom="15" maxzoom="15" strokeWidth="10" strokeWidth_2="8" /> <filter minzoom="15" maxzoom="15" strokeWidth="10" strokeWidth_2="8" />
<filter minzoom="16" maxzoom="16" strokeWidth="12" strokeWidth_2="10" /> <filter minzoom="16" maxzoom="16" strokeWidth="12" strokeWidth_2="10" />
<filter minzoom="17" maxzoom="17" strokeWidth="15" strokeWidth_2="13" /> <filter minzoom="17" maxzoom="17" strokeWidth="15" strokeWidth_2="13" />
<filter minzoom="18" strokeWidth="20" strokeWidth_2="18" /> <filter minzoom="18" strokeWidth="20" strokeWidth_2="18" />
<groupFilter nightMode="true" color="#ffffff" />
</filter> </filter>
</switch> <filter shadowRadius="1">
<filter minzoom="14" maxzoom="14" strokeWidth="6" />
<filter minzoom="15" maxzoom="15" strokeWidth="8" />
<filter minzoom="16" maxzoom="16" strokeWidth="10" />
<!-- radius 0 to avoid showing many black lines, but removed again due to bad visibility on some backgrounds -->
<filter minzoom="17" maxzoom="17" strokeWidth="13" />
<filter minzoom="18" strokeWidth="18" />
<groupFilter layer="-1" pathEffect="4_4"/>
</filter> </filter>
</groupFilter>
</group> </group>
<switch> <group>
<case tag="highway" value="road" /> <filter tag="highway" value="road" />
<case tag="highway" value="unclassified" /> <filter tag="highway" value="unclassified" />
<case tag="highway" value="residential" /> <filter tag="highway" value="residential" />
<filter> <groupFilter>
<switch> <filter hmRendered="true" minzoom="12" maxzoom="12" strokeWidth="3" />
<case nightMode="true" color="#9F9F9F" color_2="#9F9F9F" shadowColor="#666666" shadowRadius="1" />
<case nightMode="false" color="#ffffff" color_2="#ffffff" shadowColor="#464646" shadowRadius="1" />
<filter>
<!- ZM <filter minzoom="12" maxzoom="12" strokeWidth="3" /> ->
<filter minzoom="13" maxzoom="13" strokeWidth="4" /> <filter minzoom="13" maxzoom="13" strokeWidth="4" />
<switch> <!-- bridge -->
<case layer="-1" pathEffect="4_4" /> <filter layer="1" cap_2="SQUARE" color="#000000" color_2="#ffffff" shadowColor="#464646" >
<case /> <!- all other cases -> <filter minzoom="14" maxzoom="14" strokeWidth="8" strokeWidth_2="6" />
<filter>
<filter minzoom="14" maxzoom="14" strokeWidth="6" />
<filter minzoom="15" maxzoom="15" strokeWidth="8" />
<filter minzoom="16" maxzoom="16" strokeWidth="10" />
<!- radius 0 to avoid showing many black lines, but removed again due to bad visibility on some backgrounds ->
<filter minzoom="17" maxzoom="17" strokeWidth="13" />
<filter minzoom="18" strokeWidth="18" />
</filter>
</switch>
</filter>
</switch>
<!- bridge ->
<switch>
<case nightMode="false" color="#000000" color_2="#ffffff" shadowColor="#464646" />
<case nightMode="true" color="#ffffff" color_2="#9F9F9F" shadowColor="#666666" />
<filter layer="1" cap_2="SQUARE" >
<filter minzoom="13" maxzoom="14" strokeWidth="8" strokeWidth_2="6" />
<filter minzoom="15" maxzoom="15" strokeWidth="10" strokeWidth_2="8" /> <filter minzoom="15" maxzoom="15" strokeWidth="10" strokeWidth_2="8" />
<filter minzoom="16" maxzoom="16" strokeWidth="12" strokeWidth_2="10" /> <filter minzoom="16" maxzoom="16" strokeWidth="12" strokeWidth_2="10" />
<filter minzoom="17" maxzoom="17" strokeWidth="15" strokeWidth_2="13" /> <filter minzoom="17" maxzoom="17" strokeWidth="15" strokeWidth_2="13" />
<filter minzoom="18" strokeWidth="20" strokeWidth_2="18" /> <filter minzoom="18" strokeWidth="20" strokeWidth_2="18" />
<groupFilter nightMode="true" color="#ffffff" color_2="#9F9F9F" shadowColor="#666666" />
</filter> </filter>
</switch> <filter shadowRadius="1" color="#ffffff" color_2="#ffffff" shadowColor="#464646">
<filter minzoom="14" maxzoom="14" strokeWidth="6" />
<filter minzoom="15" maxzoom="15" strokeWidth="8" />
<filter minzoom="16" maxzoom="16" strokeWidth="10" />
<!-- radius 0 to avoid showing many black lines, but removed again due to bad visibility on some backgrounds -->
<filter minzoom="17" maxzoom="17" strokeWidth="13" />
<filter minzoom="18" strokeWidth="18" />
<groupFilter layer="-1" pathEffect="4_4"/>
<groupFilter nightMode="true" color="#9F9F9F" color_2="#9F9F9F" shadowColor="#666666"/>
</filter> </filter>
</switch> </groupFilter>
</group>
<switch> <group>
<case tag="highway" value="service" color="#ececec" color_2="#ececec" shadowColor="#b0b0b0" /> <filter tag="highway" value="service" color="#ececec" color_2="#ececec" shadowColor="#b0b0b0" />
<case tag="highway" value="living_street" color="#ececec" color_2="#ececec" shadowColor="#b0b0b0" /> <filter tag="highway" value="living_street" color="#ececec" color_2="#ececec" shadowColor="#b0b0b0" />
<case tag="highway" value="pedestrian" color="#ececec" color_2="#ececec" shadowColor="#b0b0b0" /> <filter tag="highway" value="pedestrian" color="#ececec" color_2="#ececec" shadowColor="#b0b0b0" />
<filter shadowRadius="1"> <groupFilter shadowRadius="1">
<switch> <filter hmRendered="true" minzoom="13" maxzoom="13" strokeWidth="2" />
<case layer="-1" pathEffect="4_4" /> <filter hmRendered="true" minzoom="14" maxzoom="14" strokeWidth="3" />
<case layer="1" nightMode="false" cap_2="SQUARE" color="#000000" />
<case layer="1" nightMode="true" cap_2="SQUARE" color="#000000" />
<case /> <!- all other cases ->
<filter>
<!- ZM <filter minzoom="13" maxzoom="13" strokeWidth="2" />
<filter minzoom="14" maxzoom="14" strokeWidth="3" /> ->
<object minzoom="15" maxzoom="15" strokeWidth="4">
<object layer="1" cap_2="SQUARE" strokeWidth="6" strokeWidth_2="4" />
</object>
<filter minzoom="16" maxzoom="16" strokeWidth="5" />
<filter minzoom="17" maxzoom="17" strokeWidth="8" />
<filter minzoom="18" strokeWidth="12"/>
</filter>
</switch>
<!- bridge ->
<switch>
<filter layer="1" cap_2="SQUARE">
<!- ZM <filter minzoom="13" maxzoom="14" strokeWidth="5" strokeWidth_2="3" /> ->
<!-- bridge -->
<filter layer="1" cap_2="SQUARE" color="#000000" color_2="#ffffff" shadowColor="#464646" >
<filter hmRendered="true" minzoom="13" maxzoom="14" strokeWidth="5" strokeWidth_2="3" />
<filter minzoom="15" maxzoom="15" strokeWidth="6" strokeWidth_2="4" />
<filter minzoom="16" maxzoom="16" strokeWidth="7" strokeWidth_2="5" /> <filter minzoom="16" maxzoom="16" strokeWidth="7" strokeWidth_2="5" />
<filter minzoom="17" maxzoom="17" strokeWidth="10" strokeWidth_2="8" /> <filter minzoom="17" maxzoom="17" strokeWidth="10" strokeWidth_2="8" />
<filter minzoom="18" strokeWidth="14" strokeWidth_2="12" /> <filter minzoom="18" strokeWidth="14" strokeWidth_2="12" />
<groupFilter nightMode="true" color="#000000"/>
</filter> </filter>
</switch> <filter shadowRadius="1" color="#ffffff" color_2="#ffffff" shadowColor="#464646">
<filter minzoom="15" maxzoom="15" strokeWidth="4" />
<filter minzoom="16" maxzoom="16" strokeWidth="5" />
<filter minzoom="17" maxzoom="17" strokeWidth="8" />
<filter minzoom="18" strokeWidth="12"/>
<groupFilter layer="-1" pathEffect="4_4"/>
</filter> </filter>
</switch> </groupFilter>
<!- TODO END --> </group>
<filter tag="highway" value="cycleway"> <filter tag="highway" value="cycleway">
<filter layer="1" minzoom="14" maxzoom="15" color="#0000ff" strokeWidth="1" pathEffect="2_2" /> <filter layer="1" minzoom="14" maxzoom="15" color="#0000ff" strokeWidth="1" pathEffect="2_2" />

View file

@ -15,9 +15,9 @@ import net.osmand.osm.LatLon;
import net.osmand.plus.activities.ApplicationMode; import net.osmand.plus.activities.ApplicationMode;
import net.osmand.plus.activities.OsmandApplication; import net.osmand.plus.activities.OsmandApplication;
import net.osmand.plus.activities.search.SearchHistoryHelper; import net.osmand.plus.activities.search.SearchHistoryHelper;
import net.osmand.plus.render.BaseOsmandRender;
import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.routing.RouteProvider.RouteService; import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.render.RenderingRulesStorage;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
@ -143,7 +143,7 @@ public class OsmandSettings {
} }
// update vector renderer // update vector renderer
RendererRegistry registry = ctx.getRendererRegistry(); RendererRegistry registry = ctx.getRendererRegistry();
BaseOsmandRender newRenderer = registry.getRenderer(RENDERER.get()); RenderingRulesStorage newRenderer = registry.getRenderer(RENDERER.get());
if (newRenderer == null) { if (newRenderer == null) {
newRenderer = registry.defaultRender(); newRenderer = registry.defaultRender();
} }
@ -1001,7 +1001,7 @@ public class OsmandSettings {
if(val == null){ if(val == null){
val = RendererRegistry.DEFAULT_RENDER; val = RendererRegistry.DEFAULT_RENDER;
} }
BaseOsmandRender loaded = ctx.getRendererRegistry().getRenderer(val); RenderingRulesStorage loaded = ctx.getRendererRegistry().getRenderer(val);
if (loaded != null) { if (loaded != null) {
ctx.getRendererRegistry().setCurrentSelectedRender(loaded); ctx.getRendererRegistry().setCurrentSelectedRender(loaded);
super.setValue(prefs, val); super.setValue(prefs, val);
@ -1011,10 +1011,12 @@ public class OsmandSettings {
return false; return false;
}; };
}; };
public final CommonPreference<String> RENDERER_APP_NAME = new StringPreference("renderer_appName", "", false);
{ {
RENDERER.setModeDefaultValue(ApplicationMode.CAR, RendererRegistry.CAR_RENDER); RENDERER.setModeDefaultValue(ApplicationMode.CAR, "car");
RENDERER.setModeDefaultValue(ApplicationMode.PEDESTRIAN, RendererRegistry.PEDESTRIAN_RENDER); RENDERER.setModeDefaultValue(ApplicationMode.PEDESTRIAN, "pedestrian");
RENDERER.setModeDefaultValue(ApplicationMode.BICYCLE, RendererRegistry.BICYCLE_RENDER); RENDERER.setModeDefaultValue(ApplicationMode.BICYCLE, "bicycle");
} }

View file

@ -36,8 +36,8 @@ import net.osmand.plus.AsyncLoadingThread.MapLoadRequest;
import net.osmand.plus.AsyncLoadingThread.TileLoadDownloadRequest; import net.osmand.plus.AsyncLoadingThread.TileLoadDownloadRequest;
import net.osmand.plus.AsyncLoadingThread.TransportLoadRequest; import net.osmand.plus.AsyncLoadingThread.TransportLoadRequest;
import net.osmand.plus.activities.OsmandApplication; import net.osmand.plus.activities.OsmandApplication;
import net.osmand.plus.render.BaseOsmandRender;
import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.render.RenderingRulesStorage;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
@ -435,7 +435,7 @@ public class ResourceManager {
context.getRendererRegistry().setExternalRenderers(externalRenderers); context.getRendererRegistry().setExternalRenderers(externalRenderers);
String r = context.getSettings().RENDERER.get(); String r = context.getSettings().RENDERER.get();
if(r != null){ if(r != null){
BaseOsmandRender obj = context.getRendererRegistry().getRenderer(r); RenderingRulesStorage obj = context.getRendererRegistry().getRenderer(r);
if(obj != null){ if(obj != null){
context.getRendererRegistry().setCurrentSelectedRender(obj); context.getRendererRegistry().setCurrentSelectedRender(obj);
} }

View file

@ -160,7 +160,7 @@ public class DownloadFileHelper {
fs = toIndex; fs = toIndex;
first = false; first = false;
} else { } else {
String name = entry.getAttrName(); String name = entry.getName();
// small simplification // small simplification
int ind = name.lastIndexOf('_'); int ind = name.lastIndexOf('_');
if (ind > 0) { if (ind > 0) {
@ -174,7 +174,7 @@ public class DownloadFileHelper {
toIndex = fs; toIndex = fs;
} }
} else { } else {
fs = new File(fileToUnZip, entry.getAttrName()); fs = new File(fileToUnZip, entry.getName());
} }
out = new FileOutputStream(fs); out = new FileOutputStream(fs);
int read; int read;

View file

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

View file

@ -19,6 +19,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.osmand.Algoritms;
import net.osmand.IProgress; import net.osmand.IProgress;
import net.osmand.LogUtil; import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapDataObject; import net.osmand.binary.BinaryMapDataObject;
@ -35,7 +36,8 @@ import net.osmand.plus.R;
import net.osmand.plus.RotatedTileBox; import net.osmand.plus.RotatedTileBox;
import net.osmand.plus.activities.OsmandApplication; import net.osmand.plus.activities.OsmandApplication;
import net.osmand.plus.render.OsmandRenderer.RenderingContext; import net.osmand.plus.render.OsmandRenderer.RenderingContext;
import net.osmand.render.OsmandRenderingRulesParser; import net.osmand.render.RenderingRuleSearchRequest;
import net.osmand.render.RenderingRulesStorage;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -57,7 +59,6 @@ public class MapRenderRepositories {
private static String BASEMAP_NAME = "basemap"; private static String BASEMAP_NAME = "basemap";
// lat/lon box of requested vector data // lat/lon box of requested vector data
private RectF cObjectsBox = new RectF(); private RectF cObjectsBox = new RectF();
// cached objects in order to render rotation without reloading data from db // cached objects in order to render rotation without reloading data from db
@ -81,7 +82,8 @@ public class MapRenderRepositories {
private RenderingContext currentRenderingContext; private RenderingContext currentRenderingContext;
private SearchRequest<BinaryMapDataObject> searchRequest; private SearchRequest<BinaryMapDataObject> searchRequest;
private OsmandSettings prefs; private OsmandSettings prefs;
public MapRenderRepositories(Context context){
public MapRenderRepositories(Context context) {
this.context = context; this.context = context;
this.renderer = new OsmandRenderer(context); this.renderer = new OsmandRenderer(context);
handler = new Handler(Looper.getMainLooper()); handler = new Handler(Looper.getMainLooper());
@ -92,10 +94,9 @@ public class MapRenderRepositories {
return context; return context;
} }
public BinaryMapIndexReader initializeNewResource(final IProgress progress, File file) { public BinaryMapIndexReader initializeNewResource(final IProgress progress, File file) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
if(files.containsKey(file.getAbsolutePath())){ if (files.containsKey(file.getAbsolutePath())) {
closeConnection(files.get(file.getAbsolutePath()), file.getAbsolutePath()); closeConnection(files.get(file.getAbsolutePath()), file.getAbsolutePath());
} }
RandomAccessFile raf = null; RandomAccessFile raf = null;
@ -103,14 +104,14 @@ public class MapRenderRepositories {
try { try {
raf = new RandomAccessFile(file, "r"); //$NON-NLS-1$ raf = new RandomAccessFile(file, "r"); //$NON-NLS-1$
reader = new BinaryMapIndexReader(raf); reader = new BinaryMapIndexReader(raf);
if(reader.getVersion() != IndexConstants.BINARY_MAP_VERSION){ if (reader.getVersion() != IndexConstants.BINARY_MAP_VERSION) {
return null; return null;
} }
files.put(file.getAbsolutePath(), reader); files.put(file.getAbsolutePath(), reader);
} catch (IOException e) { } catch (IOException e) {
log.error("No connection or unsupported version", e); //$NON-NLS-1$ log.error("No connection or unsupported version", e); //$NON-NLS-1$
if(raf != null){ if (raf != null) {
try { try {
raf.close(); raf.close();
} catch (IOException e1) { } catch (IOException e1) {
@ -118,7 +119,7 @@ public class MapRenderRepositories {
} }
return null; return null;
} catch (OutOfMemoryError oome) { } catch (OutOfMemoryError oome) {
if(raf != null){ if (raf != null) {
try { try {
raf.close(); raf.close();
} catch (IOException e1) { } catch (IOException e1) {
@ -140,7 +141,7 @@ public class MapRenderRepositories {
return prevBmpLocation; return prevBmpLocation;
} }
protected void closeConnection(BinaryMapIndexReader c, String file){ protected void closeConnection(BinaryMapIndexReader c, String file) {
files.remove(file); files.remove(file);
try { try {
c.close(); c.close();
@ -160,60 +161,59 @@ public class MapRenderRepositories {
return false; return false;
} }
public void clearAllResources(){ public void clearAllResources() {
clearCache(); clearCache();
for(String f : new ArrayList<String>(files.keySet())){ for (String f : new ArrayList<String>(files.keySet())) {
closeConnection(files.get(f), f); closeConnection(files.get(f), f);
} }
} }
public boolean updateMapIsNeeded(RotatedTileBox box) {
public boolean updateMapIsNeeded(RotatedTileBox box){
if (files.isEmpty() || box == null) { if (files.isEmpty() || box == null) {
return false; return false;
} }
if(requestedBox == null){ if (requestedBox == null) {
return true; return true;
} }
if(requestedBox.getZoom() != box.getZoom()){ if (requestedBox.getZoom() != box.getZoom()) {
return true; return true;
} }
float deltaRotate = requestedBox.getRotate() - box.getRotate(); float deltaRotate = requestedBox.getRotate() - box.getRotate();
if(deltaRotate > 180){ if (deltaRotate > 180) {
deltaRotate -= 360; deltaRotate -= 360;
} else if(deltaRotate < -180){ } else if (deltaRotate < -180) {
deltaRotate += 360; deltaRotate += 360;
} }
if(Math.abs(deltaRotate) > 25){ if (Math.abs(deltaRotate) > 25) {
return true; return true;
} }
return !requestedBox.containsTileBox(box); return !requestedBox.containsTileBox(box);
} }
public boolean isEmpty(){ public boolean isEmpty() {
return files.isEmpty(); return files.isEmpty();
} }
public void interruptLoadingMap(){ public void interruptLoadingMap() {
interrupted = true; interrupted = true;
if(currentRenderingContext != null){ if (currentRenderingContext != null) {
currentRenderingContext.interrupted = true; currentRenderingContext.interrupted = true;
} }
if(searchRequest != null){ if (searchRequest != null) {
searchRequest.setInterrupted(true); searchRequest.setInterrupted(true);
} }
} }
private boolean checkWhetherInterrupted(){ private boolean checkWhetherInterrupted() {
if(interrupted || (currentRenderingContext != null && currentRenderingContext.interrupted)){ if (interrupted || (currentRenderingContext != null && currentRenderingContext.interrupted)) {
requestedBox = bmpLocation; requestedBox = bmpLocation;
return true; return true;
} }
return false; return false;
} }
public boolean basemapExists(){ public boolean basemapExists() {
for (String f : files.keySet()) { for (String f : files.keySet()) {
if (f.toLowerCase().contains(BASEMAP_NAME)) { if (f.toLowerCase().contains(BASEMAP_NAME)) {
return true; return true;
@ -222,7 +222,7 @@ public class MapRenderRepositories {
return false; 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 cBottomLatitude = dataBox.bottom;
double cTopLatitude = dataBox.top; double cTopLatitude = dataBox.top;
double cLeftLongitude = dataBox.left; double cLeftLongitude = dataBox.left;
@ -256,13 +256,18 @@ public class MapRenderRepositories {
int type = types.get(j); int type = types.get(j);
int mask = type & 3; int mask = type & 3;
TagValuePair pair = root.decodeType(type); TagValuePair pair = root.decodeType(type);
if (pair != null && renderingType.isObjectVisible(pair.tag, pair.value, zoom, mask, nightMode)) { if (pair != null) {
renderingReq.setInitialTagValueZoom(pair.tag, pair.value, zoom);
if (renderingReq.search(mask)) {
return true; return true;
} }
if(pair != null && mask == OsmandRenderingRulesParser.POINT_STATE && if (mask == RenderingRulesStorage.POINT_RULES) {
renderingType.isObjectVisible(pair.tag, pair.value, zoom, OsmandRenderingRulesParser.TEXT_STATE, nightMode)){ if (renderingReq.search(RenderingRulesStorage.TEXT_RULES)) {
return true; return true;
} }
}
}
} }
return false; return false;
} }
@ -283,7 +288,7 @@ public class MapRenderRepositories {
} }
for (String mapName : files.keySet()) { for (String mapName : files.keySet()) {
if(basemapSearch && !mapName.toLowerCase().contains(BASEMAP_NAME)){ if (basemapSearch && !mapName.toLowerCase().contains(BASEMAP_NAME)) {
continue; continue;
} }
BinaryMapIndexReader c = files.get(mapName); BinaryMapIndexReader c = files.get(mapName);
@ -299,12 +304,12 @@ public class MapRenderRepositories {
} }
count++; 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) { if ((r.getTypes()[i] & 0x3) == MapRenderingTypes.MULTY_POLYGON_TYPE) {
// multy polygon r.getId() >> 3 // multy polygon r.getId() >> 3
TagValuePair pair = r.getMapIndex().decodeType(MapRenderingTypes.getMainObjectType(r.getTypes()[i]), TagValuePair pair = r.getMapIndex().decodeType(MapRenderingTypes.getMainObjectType(r.getTypes()[i]),
MapRenderingTypes.getObjectSubType(r.getTypes()[i])); MapRenderingTypes.getObjectSubType(r.getTypes()[i]));
if(pair != null){ if (pair != null) {
pair = new TagValuePair(pair.tag, pair.value, r.getTypes()[i]); pair = new TagValuePair(pair.tag, pair.value, r.getTypes()[i]);
if (!multiPolygons.containsKey(pair)) { if (!multiPolygons.containsKey(pair)) {
multiPolygons.put(pair, new ArrayList<BinaryMapDataObject>()); multiPolygons.put(pair, new ArrayList<BinaryMapDataObject>());
@ -334,34 +339,40 @@ public class MapRenderRepositories {
return true; return true;
} }
private void validateLatLonBox(RectF box) {
private void validateLatLonBox(RectF box){ if (box.top > 90) {
if(box.top > 90){
box.top = 85.5f; box.top = 85.5f;
} }
if(box.bottom < -90){ if (box.bottom < -90) {
box.bottom = -85.5f; box.bottom = -85.5f;
} }
if(box.left <= -180){ if (box.left <= -180) {
box.left = -179.5f; box.left = -179.5f;
} }
if(box.right > 180){ if (box.right > 180) {
box.right = 180.0f; box.right = 180.0f;
} }
} }
public synchronized void loadMap(RotatedTileBox tileRect, List<IMapDownloaderCallback> notifyList) { public synchronized void loadMap(RotatedTileBox tileRect, List<IMapDownloaderCallback> notifyList) {
interrupted = false; interrupted = false;
if(currentRenderingContext != null){ if (currentRenderingContext != null) {
currentRenderingContext = null; currentRenderingContext = null;
} }
try { try {
// find selected rendering type // find selected rendering type
OsmandApplication app = ((OsmandApplication)context.getApplicationContext()); OsmandApplication app = ((OsmandApplication) context.getApplicationContext());
Boolean renderDay = app.getDaynightHelper().getDayNightRenderer(); Boolean renderDay = app.getDaynightHelper().getDayNightRenderer();
boolean nightMode = renderDay != null && !renderDay.booleanValue(); boolean nightMode = renderDay != null && !renderDay.booleanValue();
// boolean moreDetail = prefs.SHOW_MORE_MAP_DETAIL.get(); // boolean moreDetail = prefs.SHOW_MORE_MAP_DETAIL.get();
BaseOsmandRender renderingType = app.getRendererRegistry().getCurrentSelectedRenderer(); RenderingRulesStorage storage = app.getRendererRegistry().getCurrentSelectedRenderer();
RenderingRuleSearchRequest renderingReq = new RenderingRuleSearchRequest(storage);
// TODO pass all global parameters
renderingReq.setBooleanFilter(renderingReq.ALL.R_NIGHT_MODE, nightMode);
if (renderingReq.ALL.get("appName") != null && !Algoritms.isEmpty(app.getSettings().RENDERER_APP_NAME.get())) {
renderingReq.setStringFilter(renderingReq.ALL.get("appName"), app.getSettings().RENDERER_APP_NAME.get());
}
renderingReq.saveState();
// prevent editing // prevent editing
requestedBox = new RotatedTileBox(tileRect); requestedBox = new RotatedTileBox(tileRect);
@ -383,7 +394,7 @@ public class MapRenderRepositories {
dataBox.bottom -= hi; dataBox.bottom -= hi;
} }
validateLatLonBox(dataBox); validateLatLonBox(dataBox);
boolean loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingType, nightMode); boolean loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingReq, nightMode);
if (!loaded || checkWhetherInterrupted()) { if (!loaded || checkWhetherInterrupted()) {
return; return;
} }
@ -406,7 +417,6 @@ public class MapRenderRepositories {
now = System.currentTimeMillis(); now = System.currentTimeMillis();
Bitmap bmp = Bitmap.createBitmap(currentRenderingContext.width, currentRenderingContext.height, Config.RGB_565); Bitmap bmp = Bitmap.createBitmap(currentRenderingContext.width, currentRenderingContext.height, Config.RGB_565);
boolean stepByStep = prefs.USE_STEP_BY_STEP_RENDERING.get(); boolean stepByStep = prefs.USE_STEP_BY_STEP_RENDERING.get();
@ -418,10 +428,8 @@ public class MapRenderRepositories {
this.bmpLocation = tileRect; this.bmpLocation = tileRect;
} }
renderer.generateNewBitmap(currentRenderingContext, cObjects, bmp, prefs.USE_ENGLISH_NAMES.get(), renderingReq,
stepByStep ? notifyList : null, storage.getBgColor(nightMode));
renderer.generateNewBitmap(currentRenderingContext, cObjects, bmp,
prefs.USE_ENGLISH_NAMES.get(), renderingType, stepByStep ? notifyList : null);
String renderingDebugInfo = currentRenderingContext.renderingDebugInfo; String renderingDebugInfo = currentRenderingContext.renderingDebugInfo;
if (checkWhetherInterrupted()) { if (checkWhetherInterrupted()) {
currentRenderingContext = null; currentRenderingContext = null;
@ -437,13 +445,13 @@ public class MapRenderRepositories {
this.prevBmp = null; this.prevBmp = null;
this.prevBmpLocation = null; this.prevBmpLocation = null;
} }
if(prefs.DEBUG_RENDERING_INFO.get()){ if (prefs.DEBUG_RENDERING_INFO.get()) {
String timeInfo = "Search done in "+ searchTime+" ms"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ String timeInfo = "Search done in " + searchTime + " ms"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
if(renderingDebugInfo != null){ if (renderingDebugInfo != null) {
timeInfo += "\n"+renderingDebugInfo; timeInfo += "\n" + renderingDebugInfo;
} }
final String msg = timeInfo; final String msg = timeInfo;
handler.post(new Runnable(){ handler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
@ -452,7 +460,7 @@ public class MapRenderRepositories {
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
log.error("Runtime memory exception", e); //$NON-NLS-1$ log.error("Runtime memory exception", e); //$NON-NLS-1$
handler.post(new Runnable(){ handler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
Toast.makeText(context, R.string.rendering_exception, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.rendering_exception, Toast.LENGTH_SHORT).show();
@ -462,7 +470,7 @@ public class MapRenderRepositories {
log.error("Out of memory error", e); //$NON-NLS-1$ log.error("Out of memory error", e); //$NON-NLS-1$
cObjects = new ArrayList<BinaryMapDataObject>(); cObjects = new ArrayList<BinaryMapDataObject>();
cObjectsBox = new RectF(); cObjectsBox = new RectF();
handler.post(new Runnable(){ handler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
Toast.makeText(context, R.string.rendering_out_of_memory, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.rendering_out_of_memory, Toast.LENGTH_SHORT).show();
@ -481,7 +489,6 @@ public class MapRenderRepositories {
return prevBmp; return prevBmp;
} }
public synchronized void clearCache() { public synchronized void clearCache() {
cObjects = new ArrayList<BinaryMapDataObject>(); cObjects = new ArrayList<BinaryMapDataObject>();
cObjectsBox = new RectF(); cObjectsBox = new RectF();
@ -489,10 +496,10 @@ public class MapRenderRepositories {
requestedBox = prevBmpLocation = bmpLocation = null; 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<MultyPolygon> listPolygons = new ArrayList<MultyPolygon>(multyPolygons.size());
List<TLongList> completedRings = new ArrayList<TLongList>(); List<TLongList> completedRings = new ArrayList<TLongList>();
List<TLongList> incompletedRings = new ArrayList<TLongList>(); List<TLongList> incompletedRings = new ArrayList<TLongList>();
@ -501,7 +508,7 @@ public class MapRenderRepositories {
for (TagValuePair type : multyPolygons.keySet()) { for (TagValuePair type : multyPolygons.keySet()) {
List<BinaryMapDataObject> directList; List<BinaryMapDataObject> directList;
List<BinaryMapDataObject> inverselist; 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)); TagValuePair directType = new TagValuePair(type.tag, type.value, type.additionalAttribute & ((1 << 15) - 1));
if (!multyPolygons.containsKey(directType)) { if (!multyPolygons.containsKey(directType)) {
inverselist = multyPolygons.get(type); inverselist = multyPolygons.get(type);
@ -523,10 +530,10 @@ public class MapRenderRepositories {
completedRingNames.clear(); completedRingNames.clear();
incompletedRingNames.clear(); incompletedRingNames.clear();
log.debug("Process multypolygon " + type.tag + " " + type.value + //$NON-NLS-1$ //$NON-NLS-2$ 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, MultyPolygon pl = processMultiPolygon(leftX, rightX, bottomY, topY, listPolygons, completedRings, incompletedRings,
completedRingNames, incompletedRingNames, type, directList, inverselist, zoom); completedRingNames, incompletedRingNames, type, directList, inverselist, zoom);
if(pl != null){ if (pl != null) {
listPolygons.add(pl); listPolygons.add(pl);
} }
} }
@ -534,8 +541,9 @@ public class MapRenderRepositories {
} }
private MultyPolygon processMultiPolygon(int leftX, int rightX, int bottomY, int topY, List<MultyPolygon> listPolygons, 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, List<TLongList> completedRings, List<TLongList> incompletedRings, List<String> completedRingNames,
TagValuePair type, List<BinaryMapDataObject> directList, List<BinaryMapDataObject> inverselist, int zoom) { List<String> incompletedRingNames, TagValuePair type, List<BinaryMapDataObject> directList,
List<BinaryMapDataObject> inverselist, int zoom) {
MultyPolygon pl = new MultyPolygon(); MultyPolygon pl = new MultyPolygon();
// delete direction last bit (to not show point) // delete direction last bit (to not show point)
pl.setTag(type.tag); pl.setTag(type.tag);
@ -564,9 +572,9 @@ public class MapRenderRepositories {
y = o.getPoint31YTile(km == 0 ? i : len - i - 1); y = o.getPoint31YTile(km == 0 ? i : len - i - 1);
boolean inside = leftX <= x && x <= rightX && y >= topY && y <= bottomY; boolean inside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
boolean lineEnded = calculateLineCoordinates(inside, x, y, pinside, px, py, leftX, rightX, bottomY, topY, coordinates); boolean lineEnded = calculateLineCoordinates(inside, x, y, pinside, px, py, leftX, rightX, bottomY, topY, coordinates);
if(lineEnded){ if (lineEnded) {
processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames, processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames, coordinates,
coordinates, o.getName()); o.getName());
// create new line if it goes outside // create new line if it goes outside
coordinates = new TLongArrayList(); coordinates = new TLongArrayList();
} }
@ -574,19 +582,19 @@ public class MapRenderRepositories {
py = y; py = y;
pinside = inside; pinside = inside;
} }
processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames, processMultipolygonLine(completedRings, incompletedRings, completedRingNames, incompletedRingNames, coordinates,
coordinates, o.getName()); o.getName());
} }
} }
if(completedRings.size() == 0 && incompletedRings.size() == 0){ if (completedRings.size() == 0 && incompletedRings.size() == 0) {
return null; return null;
} }
if (incompletedRings.size() > 0) { 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 { } else {
// due to self intersection small objects (for low zooms check only coastline) // due to self intersection small objects (for low zooms check only coastline)
if (zoom >= 13 if (zoom >= 13 || ("natural".equals(type.tag) && "coastline".equals(type.value))) { //$NON-NLS-1$//$NON-NLS-2$
|| ("natural".equals(type.tag) && "coastline".equals(type.value))) { //$NON-NLS-1$//$NON-NLS-2$
boolean clockwiseFound = false; boolean clockwiseFound = false;
for (TLongList c : completedRings) { for (TLongList c : completedRings) {
if (isClockwiseWay(c)) { if (isClockwiseWay(c)) {
@ -622,15 +630,15 @@ public class MapRenderRepositories {
} }
// Copied from MapAlgorithms // Copied from MapAlgorithms
private boolean isClockwiseWay(TLongList c){ private boolean isClockwiseWay(TLongList c) {
if(c.size() == 0){ if (c.size() == 0) {
return true; return true;
} }
// calculate middle Y // calculate middle Y
int mask = 0xffffffff; int mask = 0xffffffff;
long middleY = 0; 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 += (c.get(i) & mask);
} }
middleY /= (long) c.size(); middleY /= (long) c.size();
@ -671,9 +679,9 @@ public class MapRenderRepositories {
} }
} }
if(firstX != -360){ if (firstX != -360) {
boolean clockwise = (!firstDirectionUp) == (previousX < firstX); boolean clockwise = (!firstDirectionUp) == (previousX < firstX);
if(clockwise){ if (clockwise) {
clockwiseSum += Math.abs(previousX - firstX); clockwiseSum += Math.abs(previousX - firstX);
} else { } else {
clockwiseSum -= Math.abs(previousX - firstX); clockwiseSum -= Math.abs(previousX - firstX);
@ -687,7 +695,7 @@ public class MapRenderRepositories {
private int ray_intersect_x(int prevX, int prevY, int x, int y, int middleY) { private int ray_intersect_x(int prevX, int prevY, int x, int y, int middleY) {
// prev node above line // prev node above line
// x,y node below line // x,y node below line
if(prevY > y){ if (prevY > y) {
int tx = prevX; int tx = prevX;
int ty = prevY; int ty = prevY;
x = prevX; x = prevX;
@ -712,7 +720,7 @@ public class MapRenderRepositories {
} }
// NOT WORKING GOOD ! // NOT WORKING GOOD !
private boolean isClockwiseWayOld(TLongList c){ private boolean isClockwiseWayOld(TLongList c) {
double angle = 0; double angle = 0;
double prevAng = 0; double prevAng = 0;
int px = 0; int px = 0;
@ -743,7 +751,6 @@ public class MapRenderRepositories {
return angle < 0; return angle < 0;
} }
private void processMultipolygonLine(List<TLongList> completedRings, List<TLongList> incompletedRings, private void processMultipolygonLine(List<TLongList> completedRings, List<TLongList> incompletedRings,
List<String> completedRingsNames, List<String> incompletedRingsNames, TLongList coordinates, String name) { List<String> completedRingsNames, List<String> incompletedRingsNames, TLongList coordinates, String name) {
if (coordinates.size() > 0) { if (coordinates.size() > 0) {
@ -772,7 +779,7 @@ public class MapRenderRepositories {
} }
if (coordinates.get(0) == coordinates.get(coordinates.size() - 1)) { if (coordinates.get(0) == coordinates.get(coordinates.size() - 1)) {
completedRings.add(coordinates); completedRings.add(coordinates);
if(oldName != null){ if (oldName != null) {
completedRingsNames.add(oldName); completedRingsNames.add(oldName);
} else { } else {
completedRingsNames.add(name); completedRingsNames.add(name);
@ -789,12 +796,11 @@ public class MapRenderRepositories {
} }
} }
private void unifyIncompletedRings(List<TLongList> incompletedRings, List<TLongList> completedRings, private void unifyIncompletedRings(List<TLongList> incompletedRings, List<TLongList> completedRings, List<String> completedRingNames,
List<String> completedRingNames, List<String> incompletedRingNames, List<String> incompletedRingNames, int leftX, int rightX, int bottomY, int topY, long dbId, int zoom) {
int leftX, int rightX, int bottomY, int topY, long dbId, int zoom) {
int mask = 0xffffffff; int mask = 0xffffffff;
Set<Integer> nonvisitedRings = new LinkedHashSet<Integer>(); 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); TLongList i = incompletedRings.get(j);
int x = (int) (i.get(i.size() - 1) >> 32); int x = (int) (i.get(i.size() - 1) >> 32);
int y = (int) (i.get(i.size() - 1) & mask); int y = (int) (i.get(i.size() - 1) & mask);
@ -812,26 +818,24 @@ public class MapRenderRepositories {
float dy = (float) MapUtils.get31LatitudeY(y); float dy = (float) MapUtils.get31LatitudeY(y);
float dsy = (float) MapUtils.get31LatitudeY(sy); float dsy = (float) MapUtils.get31LatitudeY(sy);
String str; 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$ 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( System.err
MessageFormat.format(dbId + str, .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$
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$ 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( System.err
MessageFormat.format(dbId + str, .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$
dx, dy, dsx, dsy, leftX+"", topY+"", rightX+"", bottomY+"")); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
} }
} else { } else {
nonvisitedRings.add(j); nonvisitedRings.add(j);
} }
} }
for(int j = 0; j< incompletedRings.size(); j++){ for (int j = 0; j < incompletedRings.size(); j++) {
TLongList i = incompletedRings.get(j); TLongList i = incompletedRings.get(j);
String name = incompletedRingNames.get(j); String name = incompletedRingNames.get(j);
if(!nonvisitedRings.contains(j)){ if (!nonvisitedRings.contains(j)) {
continue; continue;
} }
@ -863,7 +867,7 @@ public class MapRenderRepositories {
int csy = (int) (cni.get(0) & mask); int csy = (int) (cni.get(0) & mask);
if (h % 4 == 0) { if (h % 4 == 0) {
// top // 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) { if (mindiff == UNDEFINED_MIN_DIFF || (csx - x) <= mindiff) {
mindiff = (csx - x); mindiff = (csx - x);
nextRingIndex = ni; nextRingIndex = ni;
@ -871,7 +875,7 @@ public class MapRenderRepositories {
} }
} else if (h % 4 == 1) { } else if (h % 4 == 1) {
// right // 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) { if (mindiff == UNDEFINED_MIN_DIFF || (csy - y) <= mindiff) {
mindiff = (csy - y); mindiff = (csy - y);
nextRingIndex = ni; nextRingIndex = ni;
@ -935,17 +939,16 @@ public class MapRenderRepositories {
} }
} }
completedRings.add(i); completedRings.add(i);
completedRingNames.add(name); completedRingNames.add(name);
} }
} }
private int safelyAddDelta(int number, int delta){ private int safelyAddDelta(int number, int delta) {
int res = number + delta; int res = number + delta;
if(delta > 0 && res < number){ if (delta > 0 && res < number) {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} else if(delta < 0 && res > number){ } else if (delta < 0 && res > number) {
return Integer.MIN_VALUE; return Integer.MIN_VALUE;
} }
return res; return res;
@ -954,8 +957,7 @@ public class MapRenderRepositories {
/** /**
* @return -1 if there is no instersection or x<<32 | y * @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, private long calculateIntersection(int x, int y, int px, int py, int leftX, int rightX, int bottomY, int topY) {
int bottomY, int topY){
int by = -1; int by = -1;
int bx = -1; int bx = -1;
// firstly try to search if the line goes in // firstly try to search if the line goes in
@ -1030,7 +1032,7 @@ public class MapRenderRepositories {
} }
if(px == rightX || px == leftX || py == topY || py == bottomY){ if (px == rightX || px == leftX || py == topY || py == bottomY) {
bx = px; bx = px;
by = py; by = py;
} }
@ -1054,11 +1056,11 @@ public class MapRenderRepositories {
} }
} else { } else {
long is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY); long is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY);
if(inside){ if (inside) {
// assert is != -1; // assert is != -1;
coordinates.add(is); coordinates.add(is);
coordinates.add((((long) x) << 32) | ((long) y)); coordinates.add((((long) x) << 32) | ((long) y));
} else if(is != -1){ } else if (is != -1) {
int bx = (int) (is >> 32); int bx = (int) (is >> 32);
int by = (int) (is & 0xffffffff); int by = (int) (is & 0xffffffff);
coordinates.add(is); coordinates.add(is);
@ -1071,7 +1073,6 @@ public class MapRenderRepositories {
return lineEnded; return lineEnded;
} }
public Map<String, BinaryMapIndexReader> getMetaInfoFiles() { public Map<String, BinaryMapIndexReader> getMetaInfoFiles() {
return files; return files;
} }

View file

@ -1,7 +1,7 @@
package net.osmand.plus.render; package net.osmand.plus.render;
import gnu.trove.list.array.TIntArrayList; 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -11,12 +11,16 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.osmand.Algoritms;
import net.osmand.LogUtil; import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapDataObject; import net.osmand.binary.BinaryMapDataObject;
import net.osmand.binary.BinaryMapIndexReader.TagValuePair; import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
import net.osmand.data.MapTileDownloader.IMapDownloaderCallback; import net.osmand.data.MapTileDownloader.IMapDownloaderCallback;
import net.osmand.osm.MapRenderingTypes; import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MultyPolygon; 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 net.sf.junidecode.Junidecode;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -86,19 +90,22 @@ public class OsmandRenderer {
int shieldRes = 0; int shieldRes = 0;
int textOrder = 20; int textOrder = 20;
public void fillProperties(RenderingContext rc, float centerX, float centerY){ public void fillProperties(RenderingRuleSearchRequest render, float centerX, float centerY){
this.centerX = centerX + rc.textDx; this.centerX = centerX;
this.centerY = centerY + rc.textDy; this.centerY = centerY + render.getIntPropertyValue(render.ALL.R_TEXT_DY, 0);
textColor = rc.textColor; textColor = render.getIntPropertyValue(render.ALL.R_TEXT_COLOR);
textSize = rc.textSize; if(textColor == 0){
textShadow = (int) rc.textHaloRadius; textColor = Color.BLACK;
textWrap = rc.textWrapWidth;
bold = rc.textBold;
minDistance = rc.textMinDistance;
shieldRes = rc.textShield;
if(rc.textOrder >= 0){
textOrder = rc.textOrder;
} }
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 cosRotateTileSize;
float sinRotateTileSize; 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; 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) { public OsmandRenderer(Context context) {
@ -273,7 +194,7 @@ public class OsmandRenderer {
return shaders.get(resId); 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)){ if(!map.containsKey(k)){
map.put(k, new TIntArrayList()); map.put(k, new TIntArrayList());
} }
@ -282,33 +203,33 @@ public class OsmandRenderer {
public Bitmap generateNewBitmap(RenderingContext rc, List<BinaryMapDataObject> objects, Bitmap bmp, boolean useEnglishNames, 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(); long now = System.currentTimeMillis();
// fill area // fill area
Canvas cv = new Canvas(bmp); Canvas cv = new Canvas(bmp);
if(renderer != null){ if(defaultColor != 0){
int dc = renderer.getDefaultColor(rc.nightMode); paintFillEmpty.setColor(defaultColor);
if(dc != 0){
paintFillEmpty.setColor(dc);
}
} }
cv.drawRect(0, 0, bmp.getWidth(), bmp.getHeight(), paintFillEmpty); cv.drawRect(0, 0, bmp.getWidth(), bmp.getHeight(), paintFillEmpty);
// put in order map // put in order map
int sz = objects.size(); int sz = objects.size();
int init = sz / 4; int init = sz / 4;
TFloatObjectHashMap<TIntArrayList> orderMap = new TFloatObjectHashMap<TIntArrayList>(); TIntObjectHashMap<TIntArrayList> orderMap = new TIntObjectHashMap<TIntArrayList>();
if (renderer != null) { if (render != null) {
for (int i = 0; i < sz; i++) { for (int i = 0; i < sz; i++) {
BinaryMapDataObject o = objects.get(i); BinaryMapDataObject o = objects.get(i);
int sh = i << 8; int sh = i << 8;
if (o instanceof MultyPolygon) { if (o instanceof MultyPolygon) {
int mask = MapRenderingTypes.MULTY_POLYGON_TYPE;
int layer = ((MultyPolygon) o).getLayer(); int layer = ((MultyPolygon) o).getLayer();
put(orderMap, renderer.getObjectOrder(((MultyPolygon) o).getTag(), ((MultyPolygon) o).getValue(), render.setInitialTagValueZoom(((MultyPolygon) o).getTag(), ((MultyPolygon) o).getValue(), rc.zoom);
mask, layer), sh, init); 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 { } else {
for (int j = 0; j < o.getTypes().length; j++) { for (int j = 0; j < o.getTypes().length; j++) {
// put(orderMap, BinaryMapDataObject.getOrder(o.getTypes()[j]), sh + j, init); // 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), TagValuePair pair = o.getMapIndex().decodeType(MapRenderingTypes.getMainObjectType(wholeType),
MapRenderingTypes.getObjectSubType(wholeType)); MapRenderingTypes.getObjectSubType(wholeType));
if (pair != null) { 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, init);
}
} }
} }
@ -341,7 +267,7 @@ public class OsmandRenderer {
rc.sinRotateTileSize = FloatMath.sin((float) Math.toRadians(rc.rotate)) * TILE_SIZE; rc.sinRotateTileSize = FloatMath.sin((float) Math.toRadians(rc.rotate)) * TILE_SIZE;
float[] keys = orderMap.keys(); int[] keys = orderMap.keys();
Arrays.sort(keys); Arrays.sort(keys);
int objCount = 0; int objCount = 0;
for (int k = 0; k < keys.length; k++) { for (int k = 0; k < keys.length; k++) {
@ -353,7 +279,7 @@ public class OsmandRenderer {
BinaryMapDataObject obj = objects.get(ind); BinaryMapDataObject obj = objects.get(ind);
// show text only for main type // show text only for main type
drawObj(obj, renderer, cv, rc, l, l == 0); drawObj(obj, render, cv, rc, l, l == 0);
objCount++; 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++; rc.allObjects++;
if (obj instanceof MultyPolygon) { if (obj instanceof MultyPolygon) {
drawMultiPolygon(obj, render,canvas, rc); drawMultiPolygon(obj, render, canvas, rc);
} else { } else {
int mainType = obj.getTypes()[l]; int mainType = obj.getTypes()[l];
int t = mainType & 3; int t = mainType & 3;
@ -707,28 +633,20 @@ public class OsmandRenderer {
return rc.tempPoint; return rc.tempPoint;
} }
public void clearCachedResources(){ public void clearCachedResources(){
cachedIcons.clear(); cachedIcons.clear();
shaders.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 tag = ((MultyPolygon)obj).getTag();
String value = ((MultyPolygon)obj).getValue(); String value = ((MultyPolygon)obj).getValue();
if(render == null || tag == null){ if(render == null || tag == null){
return; return;
} }
rc.main.emptyArea(); render.setInitialTagValueZoom(tag, value, rc.zoom);
rc.second.emptyLine(); boolean rendered = render.search(RenderingRulesStorage.POLYGON_RULES);
rc.main.color = Color.rgb(245, 245, 245); if(!rendered || !updatePaint(render, paint, 0, true)){
boolean rendered = render.renderPolygon(tag, value, rc.zoom, rc, this, rc.nightMode);
if(!rendered){
return; return;
} }
rc.visible++; rc.visible++;
@ -754,21 +672,16 @@ public class OsmandRenderer {
} }
} }
} }
rc.main.updatePaint(paint);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
// for test purpose // for test purpose
// rc.second.strokeWidth = 1.5f; // render.strokeWidth = 1.5f;
// rc.second.color = Color.BLACK; // render.color = Color.BLACK;
if (updatePaint(render, paint, 1, false)) {
if (rc.second.strokeWidth != 0) {
rc.second.updatePaint(paint);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
} }
} }
private void drawPolygon(BinaryMapDataObject obj, RenderingRuleSearchRequest render, Canvas canvas, RenderingContext rc, TagValuePair pair) {
private void drawPolygon(BinaryMapDataObject obj, BaseOsmandRender render, Canvas canvas, RenderingContext rc, TagValuePair pair) {
if(render == null || pair == null){ if(render == null || pair == null){
return; return;
} }
@ -776,12 +689,11 @@ public class OsmandRenderer {
float yText = 0; float yText = 0;
int zoom = rc.zoom; int zoom = rc.zoom;
Path path = null; 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); // rc.main.color = Color.rgb(245, 245, 245);
if(!rendered){ render.setInitialTagValueZoom(pair.tag, pair.value, zoom);
boolean rendered = render.search(RenderingRulesStorage.POLYGON_RULES);
if(!rendered || !updatePaint(render, paint, 0, true)){
return; return;
} }
rc.visible++; rc.visible++;
@ -800,11 +712,8 @@ public class OsmandRenderer {
} }
if (path != null && len > 0) { if (path != null && len > 0) {
rc.main.updatePaint(paint);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
if (rc.second.strokeWidth != 0) { if (updatePaint(render, paint, 1, false)) {
rc.second.updatePaint(paint);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
} }
String name = obj.getName(); String name = obj.getName();
@ -812,11 +721,81 @@ public class OsmandRenderer {
drawPointText(render, rc, pair, xText / len, yText / len, name); 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) { private boolean updatePaint(RenderingRuleSearchRequest req, Paint p, int ind, boolean area){
rc.clearText(); 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; String ref = null;
if (name.charAt(0) == MapRenderingTypes.REF_CHAR) { if (name.charAt(0) == MapRenderingTypes.REF_CHAR) {
ref = name.substring(1); ref = name.substring(1);
@ -833,28 +812,35 @@ public class OsmandRenderer {
} }
if (ref != null && ref.trim().length() > 0) { if (ref != null && ref.trim().length() > 0) {
rc.clearText(); render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
ref = render.renderObjectText(ref, pair.tag, pair.value, rc, true, rc.nightMode); render.setIntFilter(render.ALL.R_TEXT_LENGTH, ref.length());
render.setBooleanFilter(render.ALL.R_REF, true);
if(render.search(RenderingRulesStorage.TEXT_RULES)){
TextDrawInfo text = new TextDrawInfo(ref); TextDrawInfo text = new TextDrawInfo(ref);
text.fillProperties(rc, xText, yText); text.fillProperties(render, xText, yText);
rc.textToDraw.add(text); rc.textToDraw.add(text);
}
} }
name = render.renderObjectText(name, pair.tag, pair.value, rc, false, rc.nightMode); render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
if (rc.textSize > 0 && name != null) { render.setIntFilter(render.ALL.R_TEXT_LENGTH, name.length());
render.setBooleanFilter(render.ALL.R_REF, true);
if(render.search(RenderingRulesStorage.TEXT_RULES)){
TextDrawInfo info = new TextDrawInfo(name); TextDrawInfo info = new TextDrawInfo(name);
info.fillProperties(rc, xText, yText); info.fillProperties(render, xText, yText);
rc.textToDraw.add(info); 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){ if(render == null || pair == null){
return; 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; String name = null;
if (renderText) { if (renderText) {
name = obj.getName(); name = obj.getName();
@ -890,7 +876,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){ if(render == null || pair == null){
return; return;
} }
@ -898,16 +884,15 @@ public class OsmandRenderer {
if(length < 2){ if(length < 2){
return; return;
} }
rc.main.emptyLine(); render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
rc.second.emptyLine(); render.setIntFilter(render.ALL.R_LAYER, layer);
rc.third.emptyLine(); boolean rendered = render.search(RenderingRulesStorage.LINE_RULES);
rc.adds = null; if(!rendered || !updatePaint(render, paint, 0, false)){
boolean res = render.renderPolyline(pair.tag, pair.value, rc.zoom, rc, this, layer, rc.nightMode);
if(rc.main.strokeWidth == 0 || !res){
return; return;
} }
boolean oneway = false;
if(rc.zoom >= 16 && "highway".equals(pair.tag) && MapRenderingTypes.isOneWayWay(obj.getHighwayAttributes())){ //$NON-NLS-1$ if(rc.zoom >= 16 && "highway".equals(pair.tag) && MapRenderingTypes.isOneWayWay(obj.getHighwayAttributes())){ //$NON-NLS-1$
rc.adds = getOneWayProperties(); oneway = true;
} }
@ -953,20 +938,17 @@ public class OsmandRenderer {
yPrev = p.y; yPrev = p.y;
} }
if (path != null) { if (path != null) {
rc.main.updatePaint(paint);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
if (rc.second.strokeWidth != 0) { if (updatePaint(render, paint, 1, false)) {
rc.second.updatePaint(paint);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
if (rc.third.strokeWidth != 0) { if (updatePaint(render, paint, 2, false)) {
rc.third.updatePaint(paint);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
} }
} }
if (rc.adds != null) { if(oneway){
for (int i = 0; i < rc.adds.length; i++) { Paint[] paints = getOneWayPaints();
rc.adds[i].updatePaint(paint); for (int i = 0; i < paints.length; i++) {
canvas.drawPath(path, paint); canvas.drawPath(path, paints[i]);
} }
} }
if (obj.getName() != null && obj.getName().length() > 0) { if (obj.getName() != null && obj.getName().length() > 0) {
@ -986,22 +968,26 @@ public class OsmandRenderer {
} }
} }
if(ref != null && ref.trim().length() > 0){ if(ref != null && ref.trim().length() > 0){
rc.clearText(); render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
ref = render.renderObjectText(ref, pair.tag, pair.value, rc, true, rc.nightMode); render.setIntFilter(render.ALL.R_TEXT_LENGTH, ref.length());
render.setBooleanFilter(render.ALL.R_REF, true);
if(render.search(RenderingRulesStorage.TEXT_RULES)){
TextDrawInfo text = new TextDrawInfo(ref); TextDrawInfo text = new TextDrawInfo(ref);
text.fillProperties(rc, middlePoint.x, middlePoint.y); text.fillProperties(render, middlePoint.x, middlePoint.y);
text.pathRotate = pathRotate; text.pathRotate = pathRotate;
rc.textToDraw.add(text); rc.textToDraw.add(text);
}
} }
if(name != null && name.trim().length() > 0){ if(name != null && name.trim().length() > 0){
rc.clearText(); render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom);
name = render.renderObjectText(name, pair.tag, pair.value, rc, false, rc.nightMode); render.setIntFilter(render.ALL.R_TEXT_LENGTH, name.length());
if (rc.textSize > 0) { render.setBooleanFilter(render.ALL.R_REF, false);
if (render.search(RenderingRulesStorage.TEXT_RULES)) {
TextDrawInfo text = new TextDrawInfo(name); TextDrawInfo text = new TextDrawInfo(name);
if (!rc.showTextOnPath) { if (render.getIntPropertyValue(render.ALL.R_TEXT_ON_PATH, 0) == 0) {
text.fillProperties(rc, middlePoint.x, middlePoint.y); text.fillProperties(render, middlePoint.x, middlePoint.y);
rc.textToDraw.add(text); rc.textToDraw.add(text);
} else { } else {
paintText.setTextSize(text.textSize); paintText.setTextSize(text.textSize);
@ -1019,10 +1005,11 @@ public class OsmandRenderer {
} }
} }
} }
text.fillProperties(rc, xMid / 2, yMid / 2); text.fillProperties(render, xMid / 2, yMid / 2);
text.pathRotate = pathRotate; text.pathRotate = pathRotate;
text.drawOnPath = path; 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); rc.textToDraw.add(text);
} }
} }
@ -1032,37 +1019,36 @@ public class OsmandRenderer {
} }
} }
} }
private static RenderingPaintProperties[] oneWay = null; private static Paint[] oneWay = null;
public static RenderingPaintProperties[] getOneWayProperties(){ 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){ if(oneWay == null){
PathEffect arrowDashEffect1 = new DashPathEffect(new float[] { 0, 12, 10, 152 }, 0); PathEffect arrowDashEffect1 = new DashPathEffect(new float[] { 0, 12, 10, 152 }, 0);
PathEffect arrowDashEffect2 = new DashPathEffect(new float[] { 0, 12, 9, 153 }, 1); PathEffect arrowDashEffect2 = new DashPathEffect(new float[] { 0, 12, 9, 153 }, 1);
PathEffect arrowDashEffect3 = new DashPathEffect(new float[] { 0, 18, 2, 154 }, 1); PathEffect arrowDashEffect3 = new DashPathEffect(new float[] { 0, 18, 2, 154 }, 1);
PathEffect arrowDashEffect4 = new DashPathEffect(new float[] { 0, 18, 1, 155 }, 1); PathEffect arrowDashEffect4 = new DashPathEffect(new float[] { 0, 18, 1, 155 }, 1);
oneWay = new RenderingPaintProperties[4]; oneWay = new Paint[4];
oneWay[0] = new RenderingPaintProperties(); oneWay[0] = oneWayPaint();
oneWay[0].emptyLine(); oneWay[0].setStrokeWidth(1);
oneWay[0].color = 0xff6c70d5; oneWay[0].setPathEffect(arrowDashEffect1);
oneWay[0].strokeWidth = 1;
oneWay[0].pathEffect = arrowDashEffect1;
oneWay[1] = new RenderingPaintProperties(); oneWay[1] = oneWayPaint();
oneWay[1].emptyLine(); oneWay[1].setStrokeWidth(2);
oneWay[1].color = 0xff6c70d5; oneWay[1].setPathEffect(arrowDashEffect2);
oneWay[1].strokeWidth = 2;
oneWay[1].pathEffect = arrowDashEffect2;
oneWay[2] = new RenderingPaintProperties(); oneWay[2] = oneWayPaint();
oneWay[2].emptyLine(); oneWay[2].setStrokeWidth(3);
oneWay[2].color = 0xff6c70d5; oneWay[2].setPathEffect(arrowDashEffect3);
oneWay[2].strokeWidth = 3;
oneWay[2].pathEffect = arrowDashEffect3;
oneWay[3] = new RenderingPaintProperties(); oneWay[3] = oneWayPaint();
oneWay[3].emptyLine(); oneWay[3].setStrokeWidth(4);
oneWay[3].color = 0xff6c70d5; oneWay[3].setPathEffect(arrowDashEffect4);
oneWay[3].strokeWidth = 4;
oneWay[3].pathEffect = arrowDashEffect4;
} }
return oneWay; return oneWay;

View file

@ -4,16 +4,15 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.osmand.Algoritms;
import net.osmand.LogUtil; import net.osmand.LogUtil;
import net.osmand.render.OsmandRenderingRulesParser; import net.osmand.render.RenderingRulesStorage;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -24,72 +23,27 @@ public class RendererRegistry {
private final static Log log = LogUtil.getLog(RendererRegistry.class); private final static Log log = LogUtil.getLog(RendererRegistry.class);
public final static String DEFAULT_RENDER = "default"; //$NON-NLS-1$ 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$
private RenderingRulesStorage defaultRender = null;
private RenderingRulesStorage currentSelectedRender = null;
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 Map<String, File> externalRenderers = new LinkedHashMap<String, File>(); private Map<String, File> externalRenderers = new LinkedHashMap<String, File>();
private Map<String, String> internalRenderers = new LinkedHashMap<String, String>(); 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){ if(defaultRender == null){
defaultRender = getRenderer(DEFAULT_RENDER); 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; return defaultRender;
} }
public BaseOsmandRender carRender() { public RenderingRulesStorage getRenderer(String name){
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){
if(renderers.containsKey(name)){ if(renderers.containsKey(name)){
return renderers.get(name); return renderers.get(name);
} }
@ -103,7 +57,7 @@ public class RendererRegistry {
return externalRenderers.containsKey(name) || internalRenderers.containsKey(name); return externalRenderers.containsKey(name) || internalRenderers.containsKey(name);
} }
private BaseOsmandRender getRenderer(String name, Set<String> loadedRenderers) { private RenderingRulesStorage getRenderer(String name, Set<String> loadedRenderers) {
try { try {
return loadRenderer(name); return loadRenderer(name);
} catch (IOException e) { } catch (IOException e) {
@ -114,36 +68,33 @@ public class RendererRegistry {
return null; return null;
} }
public BaseOsmandRender loadRenderer(String name) throws IOException, SAXException { public RenderingRulesStorage loadRenderer(String name) throws IOException, SAXException {
return loadRenderer(name, new LinkedHashSet<String>()); 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; InputStream is = null;
if(externalRenderers.containsKey(name)){ if(externalRenderers.containsKey(name)){
is = new FileInputStream(externalRenderers.get(name)); is = new FileInputStream(externalRenderers.get(name));
} else if(internalRenderers.containsKey(name)){ } else if(internalRenderers.containsKey(name)){
is = OsmandRenderingRulesParser.class.getResourceAsStream(internalRenderers.get(name)); is = RenderingRulesStorage.class.getResourceAsStream(internalRenderers.get(name));
} else { } else {
throw new IllegalArgumentException("Not found " + name); //$NON-NLS-1$ throw new IllegalArgumentException("Not found " + name); //$NON-NLS-1$
} }
BaseOsmandRender b = new BaseOsmandRender(); RenderingRulesStorage b = new RenderingRulesStorage();
b.init(is); b.parseRulesFromXmlInputStream(is);
loadedRenderers.add(name); loadedRenderers.add(name);
List<BaseOsmandRender> dependencies = new ArrayList<BaseOsmandRender>(); if(!Algoritms.isEmpty(b.getDepends())){
for (String s : b.getDepends()) { if (loadedRenderers.contains(b.getDepends())) {
if (loadedRenderers.contains(s)) {
log.warn("Circular dependencies found " + name); //$NON-NLS-1$ log.warn("Circular dependencies found " + name); //$NON-NLS-1$
} else { } else {
BaseOsmandRender dep = getRenderer(s, loadedRenderers); RenderingRulesStorage dep = getRenderer(b.getDepends(), loadedRenderers);
if (dep == null) { if (dep == null) {
log.warn("Dependent renderer not found : " + name); //$NON-NLS-1$ log.warn("Dependent renderer not found : " + name); //$NON-NLS-1$
} else{ }
dependencies.add(dep); // TODO set dependent renders
} }
} }
}
b.setDependRenderers(dependencies);
renderers.put(name, b); renderers.put(name, b);
return b; return b;
} }
@ -161,14 +112,14 @@ public class RendererRegistry {
return names; return names;
} }
public BaseOsmandRender getCurrentSelectedRenderer() { public RenderingRulesStorage getCurrentSelectedRenderer() {
if(currentSelectedRender == null){ if(currentSelectedRender == null){
return defaultRender(); return defaultRender();
} }
return currentSelectedRender; return currentSelectedRender;
} }
public void setCurrentSelectedRender(BaseOsmandRender currentSelectedRender) { public void setCurrentSelectedRender(RenderingRulesStorage currentSelectedRender) {
this.currentSelectedRender = currentSelectedRender; this.currentSelectedRender = currentSelectedRender;
} }