Changeset 7054 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2014-05-03T01:07:19+02:00 (11 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
r7033 r7054 19 19 import org.openstreetmap.josm.data.osm.Node; 20 20 import org.openstreetmap.josm.data.osm.OsmPrimitive; 21 import org.openstreetmap.josm.data.osm.Relation; 22 import org.openstreetmap.josm.data.osm.Way; 21 23 import org.openstreetmap.josm.gui.mappaint.Cascade; 22 24 import org.openstreetmap.josm.gui.mappaint.Environment; … … 24 26 import org.openstreetmap.josm.gui.mappaint.Range; 25 27 import org.openstreetmap.josm.gui.mappaint.StyleSource; 28 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector; 26 29 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector; 30 import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.OptimizedGeneralSelector; 27 31 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser; 28 32 import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.ParseException; … … 42 46 public static final String MAPCSS_STYLE_MIME_TYPES = "text/x-mapcss, text/mapcss, text/css; q=0.9, text/plain; q=0.8, application/zip, application/octet-stream; q=0.5"; 43 47 44 public final List<MapCSSRule> rules; 48 // all rules 49 public final List<MapCSSRule> rules = new ArrayList<>(); 50 // rules filtered by primitive type 51 public final List<MapCSSRule> nodeRules = new ArrayList<>(); 52 public final List<MapCSSRule> wayRules = new ArrayList<>(); 53 public final List<MapCSSRule> relationRules = new ArrayList<>(); 54 public final List<MapCSSRule> multipolygonRules = new ArrayList<>(); 55 45 56 private Color backgroundColorOverride; 46 57 private String css = null; … … 49 60 public MapCSSStyleSource(String url, String name, String shortdescription) { 50 61 super(url, name, shortdescription); 51 rules = new ArrayList<>();52 62 } 53 63 54 64 public MapCSSStyleSource(SourceEntry entry) { 55 65 super(entry); 56 rules = new ArrayList<>();57 66 } 58 67 … … 68 77 CheckParameterUtil.ensureParameterNotNull(css); 69 78 this.css = css; 70 rules = new ArrayList<>();71 79 } 72 80 … … 75 83 init(); 76 84 rules.clear(); 85 nodeRules.clear(); 86 wayRules.clear(); 87 relationRules.clear(); 88 multipolygonRules.clear(); 77 89 try (InputStream in = getSourceInputStream()) { 78 90 try { … … 104 116 logError(new ParseException(e.getMessage())); // allow e to be garbage collected, it links to the entire token stream 105 117 } 106 } 107 118 // optimization: filter rules for different primitive types 119 for (MapCSSRule r: rules) { 120 List<Selector> nodeSel = new ArrayList<>(); 121 List<Selector> waySel = new ArrayList<>(); 122 List<Selector> relationSel = new ArrayList<>(); 123 List<Selector> multipolygonSel = new ArrayList<>(); 124 for (Selector sel : r.selectors) { 125 // find the rightmost selector, this must be a GeneralSelector 126 Selector selRightmost = sel; 127 while (selRightmost instanceof ChildOrParentSelector) { 128 selRightmost = ((ChildOrParentSelector) selRightmost).right; 129 } 130 Selector optimizedSel = sel.optimizedBaseCheck(); 131 switch (((GeneralSelector) selRightmost).getBase()) { 132 case "node": 133 nodeSel.add(optimizedSel); 134 break; 135 case "way": 136 waySel.add(optimizedSel); 137 break; 138 case "area": 139 waySel.add(optimizedSel); 140 multipolygonSel.add(optimizedSel); 141 break; 142 case "relation": 143 relationSel.add(optimizedSel); 144 multipolygonSel.add(optimizedSel); 145 break; 146 case "*": 147 nodeSel.add(optimizedSel); 148 waySel.add(optimizedSel); 149 relationSel.add(optimizedSel); 150 multipolygonSel.add(optimizedSel); 151 break; 152 } 153 } 154 nodeRules.add(new MapCSSRule(nodeSel, r.declaration)); 155 wayRules.add(new MapCSSRule(waySel, r.declaration)); 156 relationRules.add(new MapCSSRule(relationSel, r.declaration)); 157 multipolygonRules.add(new MapCSSRule(multipolygonSel, r.declaration)); 158 } 159 rules.clear(); 160 } 161 108 162 @Override 109 163 public InputStream getSourceInputStream() throws IOException { … … 188 242 public void apply(MultiCascade mc, OsmPrimitive osm, double scale, OsmPrimitive multipolyOuterWay, boolean pretendWayIsClosed) { 189 243 Environment env = new Environment(osm, mc, null, this); 190 RULE: for (MapCSSRule r : rules) { 244 List<MapCSSRule> matchingRules; 245 if (osm instanceof Node) { 246 matchingRules = nodeRules; 247 } else if (osm instanceof Way) { 248 matchingRules = wayRules; 249 } else { 250 if (((Relation) osm).isMultipolygon()) { 251 matchingRules = multipolygonRules; 252 } else { 253 matchingRules = relationRules; 254 } 255 } 256 RULE: for (MapCSSRule r : matchingRules) { 191 257 for (Selector s : r.selectors) { 192 258 env.clearSelectorMatchingInformation(); -
trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
r6990 r7054 22 22 import org.openstreetmap.josm.tools.Utils; 23 23 24 /** 25 * MapCSS selector. 26 * 27 * A rule has two parts, a selector and a declaration block 28 * e.g. 29 * <pre> 30 * way[highway=residential] 31 * { width: 10; color: blue; } 32 * </pre> 33 * 34 * The selector decides, if the declaration block gets applied or not. 35 * 36 * Currently all implementing classes of Selector are immutable. 37 */ 24 38 public interface Selector { 25 39 … … 32 46 * @return true, if the selector applies 33 47 */ 34 public boolean matches(Environment env); 35 36 public String getSubpart(); 37 38 public Range getRange(); 48 boolean matches(Environment env); 49 50 String getSubpart(); 51 52 Range getRange(); 53 54 /** 55 * Create an "optimized" copy of this selector that omits the base check. 56 * 57 * For the style source, the list of rules is preprocessed, such that 58 * there is a separate list of rules for nodes, ways, ... 59 * 60 * This means that the base check does not have to be performed 61 * for each rule, but only once for each primitive. 62 * 63 * @return a selector that is identical to this object, except the base of the 64 * "rightmost" selector is not checked 65 */ 66 Selector optimizedBaseCheck(); 39 67 40 68 public static enum ChildOrParentSelectorType { … … 319 347 return right.getRange(); 320 348 } 349 350 @Override 351 public Selector optimizedBaseCheck() { 352 return new ChildOrParentSelector(left, link, right.optimizedBaseCheck(), type); 353 } 321 354 322 355 @Override … … 348 381 * @return {@code true} if all conditions apply, false otherwise. 349 382 */ 350 public final boolean matchesConditions(Environment env) {383 public boolean matches(Environment env) { 351 384 if (conds == null) return true; 352 385 for (Condition c : conds) { … … 378 411 public boolean matches(Environment env) { 379 412 Utils.ensure(env.isLinkContext(), "Requires LINK context in environment, got ''{0}''", env.getContext()); 380 return matchesConditions(env);413 return super.matches(env); 381 414 } 382 415 … … 392 425 393 426 @Override 427 public Selector optimizedBaseCheck() { 428 throw new UnsupportedOperationException(); 429 } 430 431 @Override 394 432 public String toString() { 395 433 return "LinkSelector{" + "conditions=" + conds + '}'; … … 397 435 } 398 436 399 public static class GeneralSelector extends AbstractSelector { 437 public static class GeneralSelector extends OptimizedGeneralSelector { 438 439 public GeneralSelector(String base, Pair<Integer, Integer> zoom, List<Condition> conds, String subpart) { 440 super(base, zoom, conds, subpart); 441 } 442 443 public boolean matchesBase(OsmPrimitiveType type) { 444 if ("*".equals(base)) { 445 return true; 446 } else if (OsmPrimitiveType.NODE.equals(type)) { 447 return "node".equals(base); 448 } else if (OsmPrimitiveType.WAY.equals(type)) { 449 return "way".equals(base) || "area".equals(base); 450 } else if (OsmPrimitiveType.RELATION.equals(type)) { 451 return "area".equals(base) || "relation".equals(base) || "canvas".equals(base); 452 } 453 return false; 454 } 455 456 public boolean matchesBase(OsmPrimitive p) { 457 if (!matchesBase(p.getType())) { 458 return false; 459 } else { 460 if (p instanceof Relation) { 461 if ("area".equals(base)) { 462 return ((Relation) p).isMultipolygon(); 463 } else if ("canvas".equals(base)) { 464 return p.get("#canvas") != null; 465 } 466 } 467 return true; 468 } 469 } 470 471 public boolean matchesBase(Environment e) { 472 return matchesBase(e.osm); 473 } 474 475 public boolean matchesConditions(Environment e) { 476 return super.matches(e); 477 } 478 479 @Override 480 public Selector optimizedBaseCheck() { 481 return new OptimizedGeneralSelector(this); 482 } 483 484 @Override 485 public boolean matches(Environment e) { 486 return matchesBase(e) && super.matches(e); 487 } 488 } 489 490 public static class OptimizedGeneralSelector extends AbstractSelector { 400 491 public final String base; 401 492 public final Range range; 402 493 public final String subpart; 403 494 404 public GeneralSelector(String base, Pair<Integer, Integer> zoom, List<Condition> conds, String subpart) {495 public OptimizedGeneralSelector(String base, Pair<Integer, Integer> zoom, List<Condition> conds, String subpart) { 405 496 super(conds); 406 497 this.base = base; … … 418 509 this.subpart = subpart; 419 510 } 511 512 public OptimizedGeneralSelector(String base, Range range, List<Condition> conds, String subpart) { 513 super(conds); 514 this.base = base; 515 this.range = range; 516 this.subpart = subpart; 517 } 518 519 public OptimizedGeneralSelector(GeneralSelector s) { 520 this(s.base, s.range, s.conds, s.subpart); 521 } 420 522 421 523 @Override … … 428 530 } 429 531 430 public boolean matchesBase(OsmPrimitiveType type) {431 if ("*".equals(base)) {432 return true;433 } else if (OsmPrimitiveType.NODE.equals(type)) {434 return "node".equals(base);435 } else if (OsmPrimitiveType.WAY.equals(type)) {436 return "way".equals(base) || "area".equals(base);437 } else if (OsmPrimitiveType.RELATION.equals(type)) {438 return "area".equals(base) || "relation".equals(base) || "canvas".equals(base);439 }440 return false;441 }442 443 public boolean matchesBase(OsmPrimitive p) {444 if (!matchesBase(p.getType())) {445 return false;446 } else {447 if (p instanceof Relation) {448 if ("area".equals(base)) {449 return ((Relation) p).isMultipolygon();450 } else if ("canvas".equals(base)) {451 return p.get("#canvas") != null;452 }453 }454 return true;455 }456 }457 458 public boolean matchesBase(Environment e) {459 return matchesBase(e.osm);460 }461 462 @Override463 public boolean matches(Environment e) {464 return matchesBase(e) && matchesConditions(e);465 }466 467 532 public String getBase() { 468 533 return base; 469 534 } 470 535 536 @Override 537 public Selector optimizedBaseCheck() { 538 throw new UnsupportedOperationException(); 539 } 540 471 541 public static Range fromLevel(int a, int b) { 472 542 if (a > b)
Note:
See TracChangeset
for help on using the changeset viewer.