- Timestamp:
- 2014-05-18T13:20:42+02:00 (10 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java
r7069 r7138 7 7 import org.openstreetmap.josm.tools.Utils; 8 8 9 public class MapCSSRule { 9 /** 10 * A MapCSS rule. 11 * 12 * A MapCSS style is simply a list of MapCSS rules. Each rule has a selector 13 * and a declaration. Whenever the selector matches the primitive, the 14 * declaration block is executed for this primitive. 15 */ 16 public class MapCSSRule implements Comparable<MapCSSRule> { 10 17 11 18 public final Selector selector; … … 49 56 50 57 @Override 58 public int compareTo(MapCSSRule o) { 59 return declaration.idx - o.declaration.idx; 60 } 61 62 @Override 51 63 public String toString() { 52 64 return selector + " {\n " + Utils.join("\n ", declaration.instructions) + "\n}"; -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
r7125 r7138 12 12 import java.text.MessageFormat; 13 13 import java.util.ArrayList; 14 import java.util.Collection; 15 import java.util.Collections; 16 import java.util.HashMap; 17 import java.util.HashSet; 14 18 import java.util.List; 19 import java.util.Map; 15 20 import java.util.Map.Entry; 21 import java.util.Set; 16 22 import java.util.zip.ZipEntry; 17 23 import java.util.zip.ZipFile; … … 28 34 import org.openstreetmap.josm.gui.mappaint.Range; 29 35 import org.openstreetmap.josm.gui.mappaint.StyleSource; 36 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.SimpleKeyValueCondition; 30 37 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector; 31 38 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector; 39 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.OptimizedGeneralSelector; 32 40 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser; 33 41 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.ParseException; … … 49 57 // all rules 50 58 public final List<MapCSSRule> rules = new ArrayList<>(); 51 // rule sfiltered by primitive type52 public final List<MapCSSRule> nodeRules = new ArrayList<>();53 public final List<MapCSSRule> wayRules = new ArrayList<>();54 public final List<MapCSSRule> relationRules = new ArrayList<>();55 public final List<MapCSSRule> multipolygonRules = new ArrayList<>();56 public final List<MapCSSRule> canvasRules = new ArrayList<>();59 // rule indices, filtered by primitive type 60 public final MapCSSRuleIndex nodeRules = new MapCSSRuleIndex(); 61 public final MapCSSRuleIndex wayRules = new MapCSSRuleIndex(); 62 public final MapCSSRuleIndex relationRules = new MapCSSRuleIndex(); 63 public final MapCSSRuleIndex multipolygonRules = new MapCSSRuleIndex(); 64 public final MapCSSRuleIndex canvasRules = new MapCSSRuleIndex(); 57 65 58 66 private Color backgroundColorOverride; 59 67 private String css = null; 60 68 private ZipFile zipFile; 69 70 /** 71 * A collection of {@link MapCSSRule}s, that are indexed by tag key and value. 72 * 73 * Speeds up the process of finding all rules that match a certain primitive. 74 * 75 * Rules with a {@link SimpleKeyValueCondition} [key=value] are indexed by 76 * key and value in a HashMap. Now you only need to loop the tags of a 77 * primitive to retrieve the possibly matching rules. 78 * 79 * Rules with no SimpleKeyValueCondition in the selector have to be 80 * checked separately. 81 * 82 * The order of rules gets mixed up by this and needs to be sorted later. 83 */ 84 public static class MapCSSRuleIndex { 85 /* all rules for this index */ 86 public final List<MapCSSRule> rules = new ArrayList<>(); 87 /* tag based index */ 88 public final Map<String,Map<String,Set<MapCSSRule>>> index = new HashMap<>(); 89 /* rules without SimpleKeyValueCondition */ 90 public final Set<MapCSSRule> remaining = new HashSet<>(); 91 92 public void add(MapCSSRule rule) { 93 rules.add(rule); 94 } 95 96 /** 97 * Initialize the index. 98 */ 99 public void initIndex() { 100 for (MapCSSRule r: rules) { 101 // find the rightmost selector, this must be a GeneralSelector 102 Selector selRightmost = r.selector; 103 while (selRightmost instanceof ChildOrParentSelector) { 104 selRightmost = ((ChildOrParentSelector) selRightmost).right; 105 } 106 OptimizedGeneralSelector s = (OptimizedGeneralSelector) selRightmost; 107 if (s.conds == null) { 108 remaining.add(r); 109 continue; 110 } 111 List<SimpleKeyValueCondition> sk = new ArrayList<>(Utils.filteredCollection(s.conds, SimpleKeyValueCondition.class)); 112 if (sk.isEmpty()) { 113 remaining.add(r); 114 continue; 115 } 116 SimpleKeyValueCondition c = sk.get(sk.size() - 1); 117 Map<String,Set<MapCSSRule>> rulesWithMatchingKey = index.get(c.k); 118 if (rulesWithMatchingKey == null) { 119 rulesWithMatchingKey = new HashMap<>(); 120 index.put(c.k, rulesWithMatchingKey); 121 } 122 Set<MapCSSRule> rulesWithMatchingKeyValue = rulesWithMatchingKey.get(c.v); 123 if (rulesWithMatchingKeyValue == null) { 124 rulesWithMatchingKeyValue = new HashSet<>(); 125 rulesWithMatchingKey.put(c.v, rulesWithMatchingKeyValue); 126 } 127 rulesWithMatchingKeyValue.add(r); 128 } 129 } 130 131 /** 132 * Get a subset of all rules that might match the primitive. 133 * @param osm the primitive to match 134 * @return a Collection of rules that filters out most of the rules 135 * that cannot match, based on the tags of the primitive 136 */ 137 public Collection<MapCSSRule> getRuleCandidates(OsmPrimitive osm) { 138 List<MapCSSRule> ruleCandidates = new ArrayList<>(remaining); 139 for (Map.Entry<String,String> e : osm.getKeys().entrySet()) { 140 Map<String,Set<MapCSSRule>> v = index.get(e.getKey()); 141 if (v != null) { 142 Set<MapCSSRule> rs = v.get(e.getValue()); 143 if (rs != null) { 144 ruleCandidates.addAll(rs); 145 } 146 } 147 } 148 Collections.sort(ruleCandidates); 149 return ruleCandidates; 150 } 151 152 public void clear() { 153 rules.clear(); 154 index.clear(); 155 remaining.clear(); 156 } 157 } 61 158 62 159 public MapCSSStyleSource(String url, String name, String shortdescription) { … … 161 258 } 162 259 } 163 } 164 260 nodeRules.initIndex(); 261 wayRules.initIndex(); 262 relationRules.initIndex(); 263 multipolygonRules.initIndex(); 264 canvasRules.initIndex(); 265 } 266 165 267 @Override 166 268 public InputStream getSourceInputStream() throws IOException { … … 253 355 public void apply(MultiCascade mc, OsmPrimitive osm, double scale, OsmPrimitive multipolyOuterWay, boolean pretendWayIsClosed) { 254 356 Environment env = new Environment(osm, mc, null, this); 255 List<MapCSSRule> matchingRules;357 MapCSSRuleIndex matchingRuleIndex; 256 358 if (osm instanceof Node) { 257 matchingRule s= nodeRules;359 matchingRuleIndex = nodeRules; 258 360 } else if (osm instanceof Way) { 259 matchingRule s= wayRules;361 matchingRuleIndex = wayRules; 260 362 } else { 261 363 if (((Relation) osm).isMultipolygon()) { 262 matchingRule s= multipolygonRules;364 matchingRuleIndex = multipolygonRules; 263 365 } else if (osm.hasKey("#canvas")) { 264 matchingRule s= canvasRules;366 matchingRuleIndex = canvasRules; 265 367 } else { 266 matchingRule s= relationRules;267 } 268 } 269 368 matchingRuleIndex = relationRules; 369 } 370 } 371 270 372 // the declaration indices are sorted, so it suffices to save the 271 373 // last used index 272 374 int lastDeclUsed = -1; 273 375 274 for (MapCSSRule r : matchingRule s) {376 for (MapCSSRule r : matchingRuleIndex.getRuleCandidates(osm)) { 275 377 env.clearSelectorMatchingInformation(); 276 378 if (r.selector.matches(env)) { // as side effect env.parent will be set (if s is a child selector) -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
r7055 r7138 34 34 * The selector decides, if the declaration block gets applied or not. 35 35 * 36 * Currently all implementing classes of Selector are immutable.36 * All implementing classes of Selector are immutable. 37 37 */ 38 38 public interface Selector {
Note:
See TracChangeset
for help on using the changeset viewer.