Fix crash preferences/implement depends rendering style

This commit is contained in:
Victor Shcherb 2011-11-02 08:39:46 +01:00
parent ebd008e2ce
commit 62d4b19b56
8 changed files with 167 additions and 98 deletions

View file

@ -247,11 +247,11 @@ public class RenderingRuleProperty {
// Set the alpha value
color |= 0x00000000ff000000;
} else if (colorString.length() != 9) {
throw new IllegalArgumentException("Unknown color" + colorString); //$NON-NLS-1$
throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$
}
return (int)color;
}
throw new IllegalArgumentException("Unknown color" + colorString); //$NON-NLS-1$
throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$
}
public static String colorToString(int color) {

View file

@ -4,7 +4,6 @@ package net.osmand.render;
public class RenderingRuleSearchRequest {
private final RenderingRulesStorage storage;
private final RenderingRuleSearchRequest dependsRequest;
RenderingRuleProperty[] props;
int[] values;
float[] fvalues;
@ -20,11 +19,6 @@ public class RenderingRuleSearchRequest {
public RenderingRuleSearchRequest(RenderingRulesStorage storage) {
this.storage = storage;
this.ALL = storage.PROPS;
if(storage.getDependsStorage() != null){
dependsRequest = new RenderingRuleSearchRequest(storage.getDependsStorage());
} else {
dependsRequest = null;
}
props = storage.PROPS.getPoperties();
values = new int[props.length];
for (int i = 0; i < props.length; i++) {
@ -114,12 +108,7 @@ public class RenderingRuleSearchRequest {
searchResult = true;
return true;
}
if(dependsRequest != null){
// TODO search depends ?
// and copy results to local array
// dependsRequest.search(state);
}
return false;
}

View file

@ -83,12 +83,22 @@ public class RenderingRuleStorageProperties {
public RenderingRuleProperty R_TEXT_HALO_RADIUS;
public RenderingRuleProperty R_TEXT_WRAP_WIDTH;
final Map<String, RenderingRuleProperty> properties = new LinkedHashMap<String, RenderingRuleProperty>();
final Map<String, RenderingRuleProperty> properties;
// C++
final List<RenderingRuleProperty> rules = new ArrayList<RenderingRuleProperty>();
final List<RenderingRuleProperty> customRules = new ArrayList<RenderingRuleProperty>();
final List<RenderingRuleProperty> rules ;
final List<RenderingRuleProperty> customRules ;
public RenderingRuleStorageProperties() {
properties = new LinkedHashMap<String, RenderingRuleProperty>();
rules = new ArrayList<RenderingRuleProperty>();
customRules = new ArrayList<RenderingRuleProperty>();
createDefaultRenderingRuleProperties();
}
public RenderingRuleStorageProperties(RenderingRuleStorageProperties toClone) {
properties = new LinkedHashMap<String, RenderingRuleProperty>(toClone.properties);
rules = new ArrayList<RenderingRuleProperty>(toClone.rules);
customRules = new ArrayList<RenderingRuleProperty>(toClone.customRules);
createDefaultRenderingRuleProperties();
}
@ -158,15 +168,19 @@ public class RenderingRuleStorageProperties {
}
private RenderingRuleProperty registerRuleInternal(RenderingRuleProperty p) {
properties.put(p.getAttrName(), p);
p.setId(rules.size());
rules.add(p);
return p;
if(get(p.getAttrName()) == null) {
properties.put(p.getAttrName(), p);
p.setId(rules.size());
rules.add(p);
}
return get(p.getAttrName());
}
public RenderingRuleProperty registerRule(RenderingRuleProperty p) {
registerRuleInternal(p);
customRules.add(p);
return p;
RenderingRuleProperty ps = registerRuleInternal(p);
if(!customRules.contains(ps)) {
customRules.add(p);
}
return ps;
}
}

View file

@ -4,10 +4,8 @@ import gnu.trove.map.hash.TIntObjectHashMap;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -43,7 +41,7 @@ public class RenderingRulesStorage {
List<String> dictionary = new ArrayList<String>();
Map<String, Integer> dictionaryMap = new LinkedHashMap<String, Integer>();
public final RenderingRuleStorageProperties PROPS = new RenderingRuleStorageProperties();
public RenderingRuleStorageProperties PROPS = new RenderingRuleStorageProperties();
@SuppressWarnings("unchecked")
protected TIntObjectHashMap<RenderingRule>[] tagValueGlobalRules = new TIntObjectHashMap[LENGTH_RULES];
@ -51,15 +49,20 @@ public class RenderingRulesStorage {
private int bgColor = 0;
private int bgNightColor = 0;
private String renderingName;
private String depends;
private RenderingRulesStorage dependsStorage;
public static interface RenderingRulesStorageResolver {
RenderingRulesStorage resolve(String name, RenderingRulesStorageResolver ref) throws SAXException;
}
public RenderingRulesStorage(){
// register empty string as 0
getDictionaryValue("");
}
public int getDictionaryValue(String val) {
if(dictionaryMap.containsKey(val)){
return dictionaryMap.get(val);
@ -92,23 +95,41 @@ public class RenderingRulesStorage {
return nightMode ? bgNightColor : bgColor;
}
public String getDepends() {
return depends;
}
public RenderingRulesStorage getDependsStorage() {
return dependsStorage;
}
public void setDependsStorage(RenderingRulesStorage dependsStorage) {
this.dependsStorage = dependsStorage;
}
public void parseRulesFromXmlInputStream(InputStream is) throws SAXException, IOException {
public void parseRulesFromXmlInputStream(InputStream is, RenderingRulesStorageResolver resolver) throws SAXException, IOException {
try {
final SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
saxParser.parse(is, new RenderingRulesHandler(saxParser));
RenderingRulesHandler handler = new RenderingRulesHandler(saxParser, resolver);
saxParser.parse(is, handler);
RenderingRulesStorage depends = handler.getDependsStorage();
if (depends != null) {
// merge results
// dictionary,bgNightColor and props are already merged
for(int i=0; i<LENGTH_RULES; i++) {
if(depends.tagValueGlobalRules[i] == null || depends.tagValueGlobalRules[i].isEmpty()){
continue;
}
if(tagValueGlobalRules[i] != null) {
int[] keys = depends.tagValueGlobalRules[i].keys();
for (int j = 0; j < keys.length; j++) {
RenderingRule rule = tagValueGlobalRules[i].get(keys[j]);
RenderingRule dependsRule = depends.tagValueGlobalRules[i].get(keys[j]);
if (dependsRule != null) {
if (rule != null) {
RenderingRule toInsert = createRootWrapperRule(keys[j], rule);
toInsert.addIfElseChildren(dependsRule);
} else {
tagValueGlobalRules[i].put(keys[j], dependsRule);
}
}
}
} else {
tagValueGlobalRules[i] = depends.tagValueGlobalRules[i];
}
}
}
} catch (ParserConfigurationException e) {
throw new SAXException(e);
}
@ -122,7 +143,6 @@ public class RenderingRulesStorage {
}
}
@SuppressWarnings("unchecked")
private void registerGlobalRule(RenderingRule rr, int state, Map<String, String> attrsMap) throws SAXException {
int tag = rr.getIntPropertyValue(RenderingRuleStorageProperties.TAG);
if(tag == -1){
@ -137,19 +157,26 @@ public class RenderingRulesStorage {
RenderingRule previous = tagValueGlobalRules[state].get(key);
if(previous != null){
// all root rules should have at least tag/value
if(previous.getProperties().length > 2){
Map<String, String> m = new HashMap<String, String>();
m.put("tag", dictionary.get(tag));
m.put("value", dictionary.get(value));
toInsert = new RenderingRule(m, RenderingRulesStorage.this);
toInsert.addIfElseChildren(previous);
} else {
toInsert = previous;
}
toInsert = createRootWrapperRule(key, previous);
toInsert.addIfElseChildren(rr);
}
tagValueGlobalRules[state].put(key, toInsert);
}
private RenderingRule createRootWrapperRule(int tagValueKey, RenderingRule previous) {
if (previous.getProperties().length > 2) {
Map<String, String> m = new HashMap<String, String>();
m.put("tag", getTagString(tagValueKey));
m.put("value", getValueString(tagValueKey));
RenderingRule toInsert = new RenderingRule(m, RenderingRulesStorage.this);
toInsert.addIfElseChildren(previous);
return toInsert;
} else {
return previous;
}
}
private class GroupRules {
Map<String, String> groupAttributes = new LinkedHashMap<String, String>();
@ -183,10 +210,17 @@ public class RenderingRulesStorage {
Stack<Object> stack = new Stack<Object>();
Map<String, String> attrsMap = new LinkedHashMap<String, String>();
private final RenderingRulesStorageResolver resolver;
private RenderingRulesStorage dependsStorage;
public RenderingRulesHandler(SAXParser parser){
public RenderingRulesHandler(SAXParser parser, RenderingRulesStorageResolver resolver){
this.parser = parser;
this.resolver = resolver;
}
public RenderingRulesStorage getDependsStorage() {
return dependsStorage;
}
@Override
@ -267,6 +301,19 @@ public class RenderingRulesStorage {
}
PROPS.registerRule(prop);
} else if("renderingStyle".equals(name)){ //$NON-NLS-1$
String depends = attributes.getValue("depends");
if(depends != null && depends.length()> 0){
this.dependsStorage = resolver.resolve(depends, resolver);
}
if(dependsStorage != null){
bgColor = dependsStorage.bgColor;
bgNightColor = dependsStorage.bgNightColor;
// copy dictionary
dictionary = new ArrayList<String>(dependsStorage.dictionary);
dictionaryMap = new LinkedHashMap<String, Integer>(dependsStorage.dictionaryMap);
PROPS = new RenderingRuleStorageProperties(dependsStorage.PROPS);
}
String dc = attributes.getValue("defaultColor");
int defaultColor = 0;
if(dc != null && dc.length() > 0){
@ -278,7 +325,7 @@ public class RenderingRulesStorage {
bgNightColor = RenderingRuleProperty.parseColor(dnc);
}
renderingName = attributes.getValue("name");
depends = attributes.getValue("depends");
} else if("renderer".equals(name)){ //$NON-NLS-1$
throw new SAXException("Rendering style is deprecated and no longer supported.");
} else {
@ -372,38 +419,47 @@ public class RenderingRulesStorage {
for(RenderingRule rc : rr.getIfElseChildren()){
printRenderingRule(indent, rc, out);
}
}
public static void main(String[] args) throws SAXException, IOException {
RenderingRulesStorage storage = new RenderingRulesStorage();
storage.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream("new_default.render.xml"));
// storage.printDebug(LINE_RULES, System.out);
long tm = System.nanoTime();
int count = 100000;
for (int i = 0; i < count; i++) {
final RenderingRulesStorageResolver resolver = new RenderingRulesStorageResolver() {
@Override
public RenderingRulesStorage resolve(String name, RenderingRulesStorageResolver ref) throws SAXException {
RenderingRulesStorage depends = new RenderingRulesStorage();
try {
depends.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream(name+".render.xml"),
ref);
} catch (IOException e) {
throw new SAXException(e);
}
return depends;
}
};
storage.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream("test_depends.render.xml"),
resolver);
// storage.printDebug(ORDER_RULES, System.out);
// long tm = System.nanoTime();
// int count = 100000;
// for (int i = 0; i < count; i++) {
RenderingRuleSearchRequest searchRequest = new RenderingRuleSearchRequest(storage);
searchRequest.setStringFilter(storage.PROPS.R_TAG, "highway");
searchRequest.setStringFilter(storage.PROPS.R_VALUE, "motorway");
// searchRequest.setIntFilter(storage.PROPS.R_LAYER, 1);
searchRequest.setIntFilter(storage.PROPS.R_MINZOOM, 14);
searchRequest.setIntFilter(storage.PROPS.R_MAXZOOM, 14);
// searchRequest.setStringFilter(storage.PROPS.R_ORDER_TYPE, "line");
// searchRequest.setBooleanFilter(storage.PROPS.R_NIGHT_MODE, true);
searchRequest.setIntFilter(storage.PROPS.R_LAYER, 1);
searchRequest.setIntFilter(storage.PROPS.R_MINZOOM, 15);
searchRequest.setIntFilter(storage.PROPS.R_MAXZOOM, 15);
searchRequest.setIntFilter(storage.PROPS.R_ORDER_TYPE, 2);
// searchRequest.setBooleanFilter(storage.PROPS.R_NIGHT_MODE, true);
// searchRequest.setBooleanFilter(storage.PROPS.get("hmRendered"), true);
searchRequest.search(ORDER_RULES);
printResult(searchRequest, new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
}
}));
}
System.out.println((System.nanoTime()- tm)/ (1e6f * count) );
boolean res = searchRequest.search(LINE_RULES);
System.out.println("Result " + res);
printResult(searchRequest, System.out);
// }
// System.out.println((System.nanoTime()- tm)/ (1e6f * count) );
}
private static void printResult(RenderingRuleSearchRequest searchRequest, PrintStream out) {
if(searchRequest.isFound()){
out.print(" Found : ");

View file

@ -0,0 +1,8 @@
<renderingStyle name="test_depends" depends="default" defaultColor="#232323" version="1">
<!-- Test -->
<order>
<filter tag="highway" value="motorway" order="50" shadowLevel="1" orderType="2"/>
</order>
</renderingStyle>

View file

@ -23,7 +23,6 @@ import net.osmand.plus.ProgressDialogImplementation;
import net.osmand.plus.R;
import net.osmand.plus.ResourceManager;
import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.plus.views.SeekBarPreference;
import net.osmand.render.RenderingRuleProperty;
@ -289,7 +288,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
entries = (String[]) rendererNames.toArray(new String[rendererNames.size()]);
registerListPreference(osmandSettings.RENDERER, screen, entries, entries);
createCustomRenderingProperties();
createCustomRenderingProperties(false);
tileSourcePreference = (ListPreference) screen.findPreference(osmandSettings.MAP_TILE_SOURCES.getId());
tileSourcePreference.setOnPreferenceChangeListener(this);
@ -342,7 +341,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
}
}
private void createCustomRenderingProperties() {
private void createCustomRenderingProperties(boolean update) {
RenderingRulesStorage renderer = getMyApplication().getRendererRegistry().getCurrentSelectedRenderer();
PreferenceCategory cat = (PreferenceCategory) findPreference("custom_vector_rendering");
cat.removeAll();
@ -356,7 +355,6 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
lp.setSummary(p.getDescription());
cat.addPreference(lp);
LinkedHashMap<String, Object> vals = new LinkedHashMap<String, Object>();
screenPreferences.put(custom.getId(), lp);
listPreferences.put(custom.getId(), custom);
@ -367,6 +365,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
}
}
if(update) {
updateAllSettings();
}
}
}
@ -553,7 +554,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
} else {
Toast.makeText(this, R.string.renderer_load_exception, Toast.LENGTH_SHORT).show();
}
createCustomRenderingProperties();
createCustomRenderingProperties(true);
}
} else if(preference == applicationDir){
warnAboutChangingStorage((String) newValue);

View file

@ -10,9 +10,9 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import net.osmand.Algoritms;
import net.osmand.LogUtil;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.render.RenderingRulesStorage.RenderingRulesStorageResolver;
import org.apache.commons.logging.Log;
import org.xml.sax.SAXException;
@ -33,7 +33,7 @@ public class RendererRegistry {
private Map<String, RenderingRulesStorage> renderers = new LinkedHashMap<String, RenderingRulesStorage>();
public RendererRegistry(){
internalRenderers.put(DEFAULT_RENDER, "new_default.render.xml");
internalRenderers.put(DEFAULT_RENDER, "default.render.xml");
}
public RenderingRulesStorage defaultRender() {
@ -59,7 +59,7 @@ public class RendererRegistry {
private RenderingRulesStorage getRenderer(String name, Set<String> loadedRenderers) {
try {
return loadRenderer(name);
return loadRenderer(name, loadedRenderers);
} catch (IOException e) {
log.error("Error loading renderer", e); //$NON-NLS-1$
} catch (SAXException e) {
@ -68,11 +68,7 @@ public class RendererRegistry {
return null;
}
public RenderingRulesStorage loadRenderer(String name) throws IOException, SAXException {
return loadRenderer(name, new LinkedHashSet<String>());
}
private RenderingRulesStorage loadRenderer(String name, Set<String> loadedRenderers) throws IOException, SAXException {
private RenderingRulesStorage loadRenderer(String name, final Set<String> loadedRenderers) throws IOException, SAXException {
InputStream is = null;
if(externalRenderers.containsKey(name)){
is = new FileInputStream(externalRenderers.get(name));
@ -82,19 +78,24 @@ public class RendererRegistry {
throw new IllegalArgumentException("Not found " + name); //$NON-NLS-1$
}
RenderingRulesStorage main = new RenderingRulesStorage();
main.parseRulesFromXmlInputStream(is);
loadedRenderers.add(name);
if(!Algoritms.isEmpty(main.getDepends())){
if (loadedRenderers.contains(main.getDepends())) {
log.warn("Circular dependencies found " + name); //$NON-NLS-1$
} else {
RenderingRulesStorage dep = getRenderer(main.getDepends(), loadedRenderers);
main.parseRulesFromXmlInputStream(is, new RenderingRulesStorageResolver() {
@Override
public RenderingRulesStorage resolve(String name, RenderingRulesStorageResolver ref) throws SAXException {
if(renderers.containsKey(name)){
return renderers.get(name);
}
if (loadedRenderers.contains(name)) {
log.warn("Circular dependencies found " + name); //$NON-NLS-1$
}
RenderingRulesStorage dep = getRenderer(name, loadedRenderers);
if (dep == null) {
log.warn("Dependent renderer not found : " + name); //$NON-NLS-1$
}
main.setDependsStorage(dep);
return null;
}
}
});
renderers.put(name, main);
return main;
}