Changeset 7059 in josm
- Timestamp:
- 2014-05-04T13:20:39+02:00 (11 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
r7043 r7059 30 30 import java.util.Iterator; 31 31 import java.util.List; 32 import java.util.concurrent.Callable; 33 import java.util.concurrent.ExecutionException; 34 import java.util.concurrent.ExecutorService; 35 import java.util.concurrent.Executors; 36 import java.util.concurrent.Future; 32 37 33 38 import javax.swing.AbstractButton; … … 38 43 import org.openstreetmap.josm.data.coor.EastNorth; 39 44 import org.openstreetmap.josm.data.osm.BBox; 45 import org.openstreetmap.josm.data.osm.Changeset; 40 46 import org.openstreetmap.josm.data.osm.DataSet; 41 47 import org.openstreetmap.josm.data.osm.Node; … … 46 52 import org.openstreetmap.josm.data.osm.Way; 47 53 import org.openstreetmap.josm.data.osm.WaySegment; 54 import org.openstreetmap.josm.data.osm.visitor.Visitor; 48 55 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon; 49 56 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData; … … 72 79 public class StyledMapRenderer extends AbstractMapRenderer { 73 80 81 final public static int noThreads; 82 final public static ExecutorService styleCreatorPool; 83 84 static { 85 noThreads = Runtime.getRuntime().availableProcessors(); 86 styleCreatorPool = Executors.newFixedThreadPool(noThreads); 87 } 88 74 89 /** 75 90 * Iterates over a list of Way Nodes and returns screen coordinates that … … 169 184 public void remove() { 170 185 throw new UnsupportedOperationException(); 171 }172 }173 174 private class StyleCollector {175 private final boolean drawArea;176 private final boolean drawMultipolygon;177 private final boolean drawRestriction;178 179 private final List<StyleRecord> styleElems;180 181 public StyleCollector(boolean drawArea, boolean drawMultipolygon, boolean drawRestriction) {182 this.drawArea = drawArea;183 this.drawMultipolygon = drawMultipolygon;184 this.drawRestriction = drawRestriction;185 styleElems = new ArrayList<>();186 }187 188 public void add(Node osm, int flags) {189 StyleList sl = styles.get(osm, circum, nc);190 for (ElemStyle s : sl) {191 styleElems.add(new StyleRecord(s, osm, flags));192 }193 }194 195 public void add(Relation osm, int flags) {196 StyleList sl = styles.get(osm, circum, nc);197 for (ElemStyle s : sl) {198 if (drawMultipolygon && drawArea && s instanceof AreaElemStyle && (flags & FLAG_DISABLED) == 0) {199 styleElems.add(new StyleRecord(s, osm, flags));200 } else if (drawRestriction && s instanceof NodeElemStyle) {201 styleElems.add(new StyleRecord(s, osm, flags));202 }203 }204 }205 206 public void add(Way osm, int flags) {207 StyleList sl = styles.get(osm, circum, nc);208 for (ElemStyle s : sl) {209 if (!(drawArea && (flags & FLAG_DISABLED) == 0) && s instanceof AreaElemStyle) {210 continue;211 }212 styleElems.add(new StyleRecord(s, osm, flags));213 }214 }215 216 public void drawAll() {217 Collections.sort(styleElems);218 for (StyleRecord r : styleElems) {219 r.style.paintPrimitive(220 r.osm,221 paintSettings,222 StyledMapRenderer.this,223 (r.flags & FLAG_SELECTED) != 0,224 (r.flags & FLAG_MEMBER_OF_SELECTED) != 0225 );226 }227 186 } 228 187 } … … 369 328 } 370 329 371 private void collectNodeStyles(DataSet data, StyleCollector sc, BBox bbox) {372 for (final Node n: data.searchNodes(bbox)) {373 if (n.isDrawable()) {374 if (n.isDisabled()) {375 sc.add(n, FLAG_DISABLED);376 } else if (data.isSelected(n)) {377 sc.add(n, FLAG_SELECTED);378 } else if (n.isMemberOfSelected()) {379 sc.add(n, FLAG_MEMBER_OF_SELECTED);380 } else {381 sc.add(n, FLAG_NORMAL);382 }383 }384 }385 }386 387 private void collectWayStyles(DataSet data, StyleCollector sc, BBox bbox) {388 for (final Way w : data.searchWays(bbox)) {389 if (w.isDrawable()) {390 if (w.isDisabled()) {391 sc.add(w, FLAG_DISABLED);392 } else if (data.isSelected(w)) {393 sc.add(w, FLAG_SELECTED);394 } else if (w.isMemberOfSelected()) {395 sc.add(w, FLAG_MEMBER_OF_SELECTED);396 } else {397 sc.add(w, FLAG_NORMAL);398 }399 }400 }401 }402 403 private void collectRelationStyles(DataSet data, StyleCollector sc, BBox bbox) {404 for (Relation r: data.searchRelations(bbox)) {405 if (r.isDrawable()) {406 if (r.isDisabled()) {407 sc.add(r, FLAG_DISABLED);408 } else if (data.isSelected(r)) {409 sc.add(r, FLAG_SELECTED);410 } else {411 sc.add(r, FLAG_NORMAL);412 }413 }414 }415 }416 417 330 private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, GeneralPath onewayArrowsCasing, 418 331 Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) { … … 1390 1303 return null; 1391 1304 } 1392 1305 1393 1306 @Override 1394 1307 public void render(final DataSet data, boolean renderVirtualNodes, Bounds bounds) { … … 1396 1309 getSettings(renderVirtualNodes); 1397 1310 1398 boolean drawArea = circum <= Main.pref.getInteger("mappaint.fillareas", 10000000); 1399 boolean drawMultipolygon = drawArea && Main.pref.getBoolean("mappaint.multipolygon", true); 1400 boolean drawRestriction = Main.pref.getBoolean("mappaint.restriction", true); 1311 final boolean drawArea = circum <= Main.pref.getInteger("mappaint.fillareas", 10000000); 1312 final boolean drawMultipolygon = drawArea && Main.pref.getBoolean("mappaint.multipolygon", true); 1313 final boolean drawRestriction = Main.pref.getBoolean("mappaint.restriction", true); 1401 1314 1402 1315 styles = MapPaintStyles.getStyles(); … … 1412 1325 } 1413 1326 1414 StyleCollector sc = new StyleCollector(drawArea, drawMultipolygon, drawRestriction); 1415 collectNodeStyles(data, sc, bbox); 1416 collectWayStyles(data, sc, bbox); 1417 collectRelationStyles(data, sc, bbox); 1327 class ComputeStyleListWorker implements Callable<List<StyleRecord>>, Visitor { 1328 private final List<StyleRecord> styleList; 1329 private final List<? extends OsmPrimitive> input; 1330 private final int from; 1331 private final int to; 1332 1333 /** 1334 * Constructor for CreateStyleRecordsWorker. 1335 * @param input the primitives to process 1336 * @param from first index of <code>input</code> to use 1337 * @param to last index + 1 1338 */ 1339 public ComputeStyleListWorker(List<? extends OsmPrimitive> input, int from, int to) { 1340 this.styleList = new ArrayList<>(to - from); 1341 this.input = input; 1342 this.from = from; 1343 this.to = to; 1344 } 1345 1346 @Override 1347 public List<StyleRecord> call() throws Exception { 1348 for (int i = from; i<to; i++) { 1349 OsmPrimitive osm = input.get(i); 1350 if (osm.isDrawable()) { 1351 osm.accept(this); 1352 } 1353 } 1354 return styleList; 1355 } 1356 1357 @Override 1358 public void visit(Node n) { 1359 if (n.isDisabled()) { 1360 add(n, FLAG_DISABLED); 1361 } else if (data.isSelected(n)) { 1362 add(n, FLAG_SELECTED); 1363 } else if (n.isMemberOfSelected()) { 1364 add(n, FLAG_MEMBER_OF_SELECTED); 1365 } else { 1366 add(n, FLAG_NORMAL); 1367 } 1368 } 1369 1370 @Override 1371 public void visit(Way w) { 1372 if (w.isDisabled()) { 1373 add(w, FLAG_DISABLED); 1374 } else if (data.isSelected(w)) { 1375 add(w, FLAG_SELECTED); 1376 } else if (w.isMemberOfSelected()) { 1377 add(w, FLAG_MEMBER_OF_SELECTED); 1378 } else { 1379 add(w, FLAG_NORMAL); 1380 } 1381 } 1382 1383 @Override 1384 public void visit(Relation r) { 1385 if (r.isDisabled()) { 1386 add(r, FLAG_DISABLED); 1387 } else if (data.isSelected(r)) { 1388 add(r, FLAG_SELECTED); 1389 } else { 1390 add(r, FLAG_NORMAL); 1391 } 1392 } 1393 1394 @Override 1395 public void visit(Changeset cs) { 1396 throw new UnsupportedOperationException(); 1397 } 1398 1399 public void add(Node osm, int flags) { 1400 StyleList sl = styles.get(osm, circum, nc); 1401 for (ElemStyle s : sl) { 1402 styleList.add(new StyleRecord(s, osm, flags)); 1403 } 1404 } 1405 1406 public void add(Relation osm, int flags) { 1407 StyleList sl = styles.get(osm, circum, nc); 1408 for (ElemStyle s : sl) { 1409 if (drawMultipolygon && drawArea && s instanceof AreaElemStyle && (flags & FLAG_DISABLED) == 0) { 1410 styleList.add(new StyleRecord(s, osm, flags)); 1411 } else if (drawRestriction && s instanceof NodeElemStyle) { 1412 styleList.add(new StyleRecord(s, osm, flags)); 1413 } 1414 } 1415 } 1416 1417 public void add(Way osm, int flags) { 1418 StyleList sl = styles.get(osm, circum, nc); 1419 for (ElemStyle s : sl) { 1420 if (!(drawArea && (flags & FLAG_DISABLED) == 0) && s instanceof AreaElemStyle) { 1421 continue; 1422 } 1423 styleList.add(new StyleRecord(s, osm, flags)); 1424 } 1425 } 1426 } 1427 1428 final List<ComputeStyleListWorker> tasks = new ArrayList<>(); 1429 final List<StyleRecord> allStyleElems = new ArrayList<>(); 1430 1431 class ConcurrentTasksHelper { 1432 void createTasks(List<? extends OsmPrimitive> prims) { 1433 int bucketsize = Math.max(100, prims.size()/noThreads/3); 1434 for (int i=0; i*bucketsize < prims.size(); i++) { 1435 tasks.add(new ComputeStyleListWorker(prims, i*bucketsize, Math.min((i+1)*bucketsize, prims.size()))); 1436 } 1437 } 1438 1439 void runIt() { 1440 if (tasks.size() == 1) { 1441 try { 1442 allStyleElems.addAll(tasks.get(0).call()); 1443 } catch (Exception ex) { 1444 throw new RuntimeException(ex); 1445 } 1446 } else if (tasks.size() > 1) { 1447 try { 1448 for (Future<List<StyleRecord>> future : styleCreatorPool.invokeAll(tasks)) { 1449 allStyleElems.addAll(future.get()); 1450 } 1451 } catch (InterruptedException | ExecutionException ex) { 1452 throw new RuntimeException(ex); 1453 } 1454 } 1455 } 1456 } 1457 ConcurrentTasksHelper helper = new ConcurrentTasksHelper(); 1458 1459 // Need to process all relations first. 1460 // Reason: Make sure, ElemStyles.getStyleCacheWithRange is 1461 // not called for the same primtive in parallel threads. 1462 // (Could be synchronized, but try to avoid this for 1463 // performance reasons.) 1464 helper.createTasks(data.searchRelations(bbox)); 1465 helper.runIt(); 1466 1467 tasks.clear(); 1468 helper.createTasks(data.searchNodes(bbox)); 1469 helper.createTasks(data.searchWays(bbox)); 1470 helper.runIt(); 1471 1418 1472 1419 1473 if (Main.isTraceEnabled()) { … … 1422 1476 } 1423 1477 1424 sc.drawAll(); 1425 sc = null; 1478 Collections.sort(allStyleElems); 1479 1480 for (StyleRecord r : allStyleElems) { 1481 r.style.paintPrimitive( 1482 r.osm, 1483 paintSettings, 1484 StyledMapRenderer.this, 1485 (r.flags & FLAG_SELECTED) != 0, 1486 (r.flags & FLAG_MEMBER_OF_SELECTED) != 0 1487 ); 1488 } 1426 1489 1427 1490 if (Main.isTraceEnabled()) { -
trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java
r7005 r7059 86 86 * Two preference values and the set of created fonts are cached in order to avoid 87 87 * expensive lookups and to avoid too many font objects 88 * (in analogy to flyweight pattern).89 88 * 90 89 * FIXME: cached preference values are not updated if the user changes them during 91 90 * a JOSM session. Should have a listener listening to preference changes. 92 91 */ 93 private static String DEFAULT_FONT_NAME = null; 94 private static Float DEFAULT_FONT_SIZE = null; 95 private static void initDefaultFontParameters() { 96 if (DEFAULT_FONT_NAME != null) return; // already initialized - skip initialization 97 DEFAULT_FONT_NAME = Main.pref.get("mappaint.font", "Helvetica"); 98 DEFAULT_FONT_SIZE = (float) Main.pref.getInteger("mappaint.fontsize", 8); 92 private static volatile String DEFAULT_FONT_NAME = null; 93 private static volatile Float DEFAULT_FONT_SIZE = null; 94 private static final Object lock = new Object(); 95 96 // thread save access (double-checked locking) 97 private static Float getDefaultFontSize() { 98 Float s = DEFAULT_FONT_SIZE; 99 if (s == null) { 100 synchronized (lock) { 101 s = DEFAULT_FONT_SIZE; 102 if (s == null) { 103 DEFAULT_FONT_SIZE = s = (float) Main.pref.getInteger("mappaint.fontsize", 8); 104 } 105 } 106 } 107 return s; 108 } 109 110 private static String getDefaultFontName() { 111 String n = DEFAULT_FONT_NAME; 112 if (n == null) { 113 synchronized (lock) { 114 n = DEFAULT_FONT_NAME; 115 if (n == null) { 116 DEFAULT_FONT_NAME = n = Main.pref.get("mappaint.font", "Helvetica"); 117 } 118 } 119 } 120 return n; 99 121 } 100 122 … … 155 177 156 178 protected static Font getFont(Cascade c) { 157 initDefaultFontParameters(); // populated cached preferences, if necessary 158 String name = c.get("font-family", DEFAULT_FONT_NAME, String.class); 159 float size = c.get("font-size", DEFAULT_FONT_SIZE, Float.class); 179 String name = c.get("font-family", getDefaultFontName(), String.class); 180 float size = c.get("font-size", getDefaultFontSize(), Float.class); 160 181 int weight = Font.PLAIN; 161 182 if ("bold".equalsIgnoreCase(c.get("font-weight", null, String.class))) { -
trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
r7014 r7059 192 192 193 193 if (!hasIndependentLineStyle) { 194 Pair<StyleList, Range> mpElemStyles = getStyleCacheWithRange(r, scale, nc); 194 Pair<StyleList, Range> mpElemStyles; 195 synchronized(r) { 196 mpElemStyles = getStyleCacheWithRange(r, scale, nc); 197 } 195 198 ElemStyle mpLine = null; 196 199 for (ElemStyle s : mpElemStyles.a) { … … 249 252 } 250 253 if (!hasIndependentElemStyle && !multipolygon.getOuterWays().isEmpty()) { 251 StyleList mpElemStyles = get(ref, scale, nc);252 254 Color mpColor = null; 255 StyleList mpElemStyles = null; 256 synchronized (ref) { 257 mpElemStyles = get(ref, scale, nc); 258 } 253 259 for (ElemStyle mpS : mpElemStyles) { 254 260 if (mpS instanceof AreaElemStyle) {
Note:
See TracChangeset
for help on using the changeset viewer.