Changeset 11914 in josm for trunk/src/org
- Timestamp:
- 2017-04-15T02:00:43+02:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 4 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
r11893 r11914 35 35 import java.util.Optional; 36 36 import java.util.concurrent.ForkJoinPool; 37 import java.util.concurrent.ForkJoinTask;38 import java.util.concurrent.RecursiveTask;39 37 import java.util.function.BiConsumer; 40 38 import java.util.function.Consumer; … … 48 46 import org.openstreetmap.josm.data.coor.EastNorth; 49 47 import org.openstreetmap.josm.data.osm.BBox; 50 import org.openstreetmap.josm.data.osm.Changeset;51 48 import org.openstreetmap.josm.data.osm.DataSet; 52 49 import org.openstreetmap.josm.data.osm.Node; … … 57 54 import org.openstreetmap.josm.data.osm.Way; 58 55 import org.openstreetmap.josm.data.osm.WaySegment; 59 import org.openstreetmap.josm.data.osm.visitor.Visitor;60 56 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon; 61 57 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData; … … 69 65 import org.openstreetmap.josm.gui.draw.MapViewPath; 70 66 import org.openstreetmap.josm.gui.draw.MapViewPositionAndRotation; 71 import org.openstreetmap.josm.gui.mappaint.ElemStyles;72 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;73 import org.openstreetmap.josm.gui.mappaint.StyleElementList;74 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;75 import org.openstreetmap.josm.gui.mappaint.styleelement.AreaElement;76 import org.openstreetmap.josm.gui.mappaint.styleelement.AreaIconElement;77 67 import org.openstreetmap.josm.gui.mappaint.styleelement.BoxTextElement; 78 68 import org.openstreetmap.josm.gui.mappaint.styleelement.BoxTextElement.HorizontalTextAlignment; … … 83 73 import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement; 84 74 import org.openstreetmap.josm.gui.mappaint.styleelement.Symbol; 85 import org.openstreetmap.josm.gui.mappaint.styleelement.TextElement;86 75 import org.openstreetmap.josm.gui.mappaint.styleelement.TextLabel; 87 76 import org.openstreetmap.josm.gui.mappaint.styleelement.placement.PositionForAreaStrategy; … … 247 236 * Not used in any public interfaces. 248 237 */ 249 privatestatic final int FLAG_NORMAL = 0;238 static final int FLAG_NORMAL = 0; 250 239 /** 251 240 * A primitive with {@link OsmPrimitive#isDisabled()} 252 241 */ 253 privatestatic final int FLAG_DISABLED = 1;242 static final int FLAG_DISABLED = 1; 254 243 /** 255 244 * A primitive with {@link OsmPrimitive#isMemberOfSelected()} 256 245 */ 257 privatestatic final int FLAG_MEMBER_OF_SELECTED = 2;246 static final int FLAG_MEMBER_OF_SELECTED = 2; 258 247 /** 259 248 * A primitive with {@link OsmPrimitive#isSelected()} 260 249 */ 261 privatestatic final int FLAG_SELECTED = 4;250 static final int FLAG_SELECTED = 4; 262 251 /** 263 252 * A primitive with {@link OsmPrimitive#isOuterMemberOfSelected()} 264 253 */ 265 privatestatic final int FLAG_OUTERMEMBER_OF_SELECTED = 8;254 static final int FLAG_OUTERMEMBER_OF_SELECTED = 8; 266 255 267 256 private static final double PHI = Math.toRadians(20); … … 1495 1484 } 1496 1485 1497 private static class ComputeStyleListWorker extends RecursiveTask<List<StyleRecord>> implements Visitor {1498 private final transient List<? extends OsmPrimitive> input;1499 private final transient List<StyleRecord> output;1500 1501 private final transient ElemStyles styles = MapPaintStyles.getStyles();1502 private final int directExecutionTaskSize;1503 private final double circum;1504 private final NavigatableComponent nc;1505 1506 private final boolean drawArea;1507 private final boolean drawMultipolygon;1508 private final boolean drawRestriction;1509 1510 /**1511 * Constructs a new {@code ComputeStyleListWorker}.1512 * @param circum distance on the map in meters that 100 screen pixels represent1513 * @param nc navigatable component1514 * @param input the primitives to process1515 * @param output the list of styles to which styles will be added1516 * @param directExecutionTaskSize the threshold deciding whether to subdivide the tasks1517 */1518 ComputeStyleListWorker(double circum, NavigatableComponent nc,1519 final List<? extends OsmPrimitive> input, List<StyleRecord> output, int directExecutionTaskSize) {1520 this.circum = circum;1521 this.nc = nc;1522 this.input = input;1523 this.output = output;1524 this.directExecutionTaskSize = directExecutionTaskSize;1525 this.drawArea = circum <= Main.pref.getInteger("mappaint.fillareas", 10_000_000);1526 this.drawMultipolygon = drawArea && Main.pref.getBoolean("mappaint.multipolygon", true);1527 this.drawRestriction = Main.pref.getBoolean("mappaint.restriction", true);1528 this.styles.setDrawMultipolygon(drawMultipolygon);1529 }1530 1531 @Override1532 protected List<StyleRecord> compute() {1533 if (input.size() <= directExecutionTaskSize) {1534 return computeDirectly();1535 } else {1536 final Collection<ForkJoinTask<List<StyleRecord>>> tasks = new ArrayList<>();1537 for (int fromIndex = 0; fromIndex < input.size(); fromIndex += directExecutionTaskSize) {1538 final int toIndex = Math.min(fromIndex + directExecutionTaskSize, input.size());1539 final List<StyleRecord> output = new ArrayList<>(directExecutionTaskSize);1540 tasks.add(new ComputeStyleListWorker(circum, nc, input.subList(fromIndex, toIndex), output, directExecutionTaskSize).fork());1541 }1542 for (ForkJoinTask<List<StyleRecord>> task : tasks) {1543 output.addAll(task.join());1544 }1545 return output;1546 }1547 }1548 1549 public List<StyleRecord> computeDirectly() {1550 MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().lock();1551 try {1552 for (final OsmPrimitive osm : input) {1553 acceptDrawable(osm);1554 }1555 return output;1556 } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {1557 throw BugReport.intercept(e).put("input-size", input.size()).put("output-size", output.size());1558 } finally {1559 MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().unlock();1560 }1561 }1562 1563 private void acceptDrawable(final OsmPrimitive osm) {1564 try {1565 if (osm.isDrawable()) {1566 osm.accept(this);1567 }1568 } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {1569 throw BugReport.intercept(e).put("osm", osm);1570 }1571 }1572 1573 @Override1574 public void visit(Node n) {1575 add(n, computeFlags(n, false));1576 }1577 1578 @Override1579 public void visit(Way w) {1580 add(w, computeFlags(w, true));1581 }1582 1583 @Override1584 public void visit(Relation r) {1585 add(r, computeFlags(r, true));1586 }1587 1588 @Override1589 public void visit(Changeset cs) {1590 throw new UnsupportedOperationException();1591 }1592 1593 public void add(Node osm, int flags) {1594 StyleElementList sl = styles.get(osm, circum, nc);1595 for (StyleElement s : sl) {1596 output.add(new StyleRecord(s, osm, flags));1597 }1598 }1599 1600 public void add(Relation osm, int flags) {1601 StyleElementList sl = styles.get(osm, circum, nc);1602 for (StyleElement s : sl) {1603 if (drawMultipolygon && drawArea && (s instanceof AreaElement || s instanceof AreaIconElement) && (flags & FLAG_DISABLED) == 0) {1604 output.add(new StyleRecord(s, osm, flags));1605 } else if (drawMultipolygon && drawArea && s instanceof TextElement) {1606 output.add(new StyleRecord(s, osm, flags));1607 } else if (drawRestriction && s instanceof NodeElement) {1608 output.add(new StyleRecord(s, osm, flags));1609 }1610 }1611 }1612 1613 public void add(Way osm, int flags) {1614 StyleElementList sl = styles.get(osm, circum, nc);1615 for (StyleElement s : sl) {1616 if ((drawArea && (flags & FLAG_DISABLED) == 0) || !(s instanceof AreaElement)) {1617 output.add(new StyleRecord(s, osm, flags));1618 }1619 }1620 }1621 }1622 1623 1486 /** 1624 1487 * Sets the factory that creates the benchmark data receivers. -
trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
r11746 r11914 35 35 import java.util.Hashtable; 36 36 import java.util.List; 37 import java.util.Locale;38 import java.util.Objects;39 37 import java.util.Optional; 40 38 import java.util.TimeZone; … … 1251 1249 return endIndex; 1252 1250 } 1253 1254 static final class Timezone {1255 1256 static final Timezone ZERO = new Timezone(0.0);1257 private final double timezone;1258 1259 Timezone(double hours) {1260 this.timezone = hours;1261 }1262 1263 public double getHours() {1264 return timezone;1265 }1266 1267 String formatTimezone() {1268 StringBuilder ret = new StringBuilder();1269 1270 double timezone = this.timezone;1271 if (timezone < 0) {1272 ret.append('-');1273 timezone = -timezone;1274 } else {1275 ret.append('+');1276 }1277 ret.append((long) timezone).append(':');1278 int minutes = (int) ((timezone % 1) * 60);1279 if (minutes < 10) {1280 ret.append('0');1281 }1282 ret.append(minutes);1283 1284 return ret.toString();1285 }1286 1287 static Timezone parseTimezone(String timezone) throws ParseException {1288 1289 if (timezone.isEmpty())1290 return ZERO;1291 1292 String error = tr("Error while parsing timezone.\nExpected format: {0}", "+H:MM");1293 1294 char sgnTimezone = '+';1295 StringBuilder hTimezone = new StringBuilder();1296 StringBuilder mTimezone = new StringBuilder();1297 int state = 1; // 1=start/sign, 2=hours, 3=minutes.1298 for (int i = 0; i < timezone.length(); i++) {1299 char c = timezone.charAt(i);1300 switch (c) {1301 case ' ':1302 if (state != 2 || hTimezone.length() != 0)1303 throw new ParseException(error, i);1304 break;1305 case '+':1306 case '-':1307 if (state == 1) {1308 sgnTimezone = c;1309 state = 2;1310 } else1311 throw new ParseException(error, i);1312 break;1313 case ':':1314 case '.':1315 if (state == 2) {1316 state = 3;1317 } else1318 throw new ParseException(error, i);1319 break;1320 case '0':1321 case '1':1322 case '2':1323 case '3':1324 case '4':1325 case '5':1326 case '6':1327 case '7':1328 case '8':1329 case '9':1330 switch (state) {1331 case 1:1332 case 2:1333 state = 2;1334 hTimezone.append(c);1335 break;1336 case 3:1337 mTimezone.append(c);1338 break;1339 default:1340 throw new ParseException(error, i);1341 }1342 break;1343 default:1344 throw new ParseException(error, i);1345 }1346 }1347 1348 int h = 0;1349 int m = 0;1350 try {1351 h = Integer.parseInt(hTimezone.toString());1352 if (mTimezone.length() > 0) {1353 m = Integer.parseInt(mTimezone.toString());1354 }1355 } catch (NumberFormatException nfe) {1356 // Invalid timezone1357 throw (ParseException) new ParseException(error, 0).initCause(nfe);1358 }1359 1360 if (h > 12 || m > 59)1361 throw new ParseException(error, 0);1362 else1363 return new Timezone((h + m / 60.0) * (sgnTimezone == '-' ? -1 : 1));1364 }1365 1366 @Override1367 public boolean equals(Object o) {1368 if (this == o) return true;1369 if (!(o instanceof Timezone)) return false;1370 Timezone timezone1 = (Timezone) o;1371 return Double.compare(timezone1.timezone, timezone) == 0;1372 }1373 1374 @Override1375 public int hashCode() {1376 return Objects.hash(timezone);1377 }1378 }1379 1380 static final class Offset {1381 1382 static final Offset ZERO = new Offset(0);1383 private final long milliseconds;1384 1385 private Offset(long milliseconds) {1386 this.milliseconds = milliseconds;1387 }1388 1389 static Offset milliseconds(long milliseconds) {1390 return new Offset(milliseconds);1391 }1392 1393 static Offset seconds(long seconds) {1394 return new Offset(1000 * seconds);1395 }1396 1397 long getMilliseconds() {1398 return milliseconds;1399 }1400 1401 long getSeconds() {1402 return milliseconds / 1000;1403 }1404 1405 String formatOffset() {1406 if (milliseconds % 1000 == 0) {1407 return Long.toString(milliseconds / 1000);1408 } else if (milliseconds % 100 == 0) {1409 return String.format(Locale.ENGLISH, "%.1f", milliseconds / 1000.);1410 } else {1411 return String.format(Locale.ENGLISH, "%.3f", milliseconds / 1000.);1412 }1413 }1414 1415 static Offset parseOffset(String offset) throws ParseException {1416 String error = tr("Error while parsing offset.\nExpected format: {0}", "number");1417 1418 if (!offset.isEmpty()) {1419 try {1420 if (offset.startsWith("+")) {1421 offset = offset.substring(1);1422 }1423 return Offset.milliseconds(Math.round(Double.parseDouble(offset) * 1000));1424 } catch (NumberFormatException nfe) {1425 throw (ParseException) new ParseException(error, 0).initCause(nfe);1426 }1427 } else {1428 return Offset.ZERO;1429 }1430 }1431 1432 int getDayOffset() {1433 // Find day difference1434 return (int) Math.round(((double) getMilliseconds()) / TimeUnit.DAYS.toMillis(1));1435 }1436 1437 Offset withoutDayOffset() {1438 return milliseconds(getMilliseconds() - TimeUnit.DAYS.toMillis(getDayOffset()));1439 }1440 1441 Pair<Timezone, Offset> splitOutTimezone() {1442 // In hours1443 final double tz = ((double) withoutDayOffset().getSeconds()) / TimeUnit.HOURS.toSeconds(1);1444 1445 // Due to imprecise clocks we might get a "+3:28" timezone, which should obviously be 3:30 with1446 // -2 minutes offset. This determines the real timezone and finds offset.1447 final double timezone = (double) Math.round(tz * 2) / 2; // hours, rounded to one decimal place1448 final long delta = Math.round(getMilliseconds() - timezone * TimeUnit.HOURS.toMillis(1));1449 return Pair.create(new Timezone(timezone), Offset.milliseconds(delta));1450 }1451 1452 @Override1453 public boolean equals(Object o) {1454 if (this == o) return true;1455 if (!(o instanceof Offset)) return false;1456 Offset offset = (Offset) o;1457 return milliseconds == offset.milliseconds;1458 }1459 1460 @Override1461 public int hashCode() {1462 return Objects.hash(milliseconds);1463 }1464 }1465 1251 } -
trunk/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessor.java
r11553 r11914 2 2 package org.openstreetmap.josm.gui.layer.imagery; 3 3 4 import java.awt.Rectangle;5 import java.awt.RenderingHints;6 import java.awt.geom.Point2D;7 import java.awt.geom.Rectangle2D;8 4 import java.awt.image.BufferedImage; 9 import java.awt.image.BufferedImageOp;10 import java.awt.image.ColorModel;11 import java.awt.image.DataBuffer;12 import java.awt.image.DataBufferByte;13 import java.util.Optional;14 5 15 import org.openstreetmap.josm.Main;16 6 import org.openstreetmap.josm.gui.layer.ImageProcessor; 17 7 … … 65 55 return "ColorfulImageProcessor [colorfulness=" + colorfulness + ']'; 66 56 } 67 68 static class ColorfulFilter implements BufferedImageOp {69 private final double colorfulness;70 71 /**72 * Create a new colorful filter.73 * @param colorfulness The colorfulness as defined in the {@link ColorfulImageProcessor} class.74 */75 ColorfulFilter(double colorfulness) {76 this.colorfulness = colorfulness;77 }78 79 @Override80 public BufferedImage filter(BufferedImage src, BufferedImage dst) {81 if (src.getWidth() == 0 || src.getHeight() == 0) {82 return src;83 }84 85 BufferedImage dest = Optional.ofNullable(dst).orElseGet(() -> createCompatibleDestImage(src, null));86 DataBuffer srcBuffer = src.getRaster().getDataBuffer();87 DataBuffer destBuffer = dest.getRaster().getDataBuffer();88 if (!(srcBuffer instanceof DataBufferByte) || !(destBuffer instanceof DataBufferByte)) {89 Main.trace("Cannot apply color filter: Images do not use DataBufferByte.");90 return src;91 }92 93 int type = src.getType();94 if (type != dest.getType()) {95 Main.trace("Cannot apply color filter: Src / Dest differ in type (" + type + '/' + dest.getType() + ')');96 return src;97 }98 int redOffset;99 int greenOffset;100 int blueOffset;101 int alphaOffset = 0;102 switch (type) {103 case BufferedImage.TYPE_3BYTE_BGR:104 blueOffset = 0;105 greenOffset = 1;106 redOffset = 2;107 break;108 case BufferedImage.TYPE_4BYTE_ABGR:109 case BufferedImage.TYPE_4BYTE_ABGR_PRE:110 blueOffset = 1;111 greenOffset = 2;112 redOffset = 3;113 break;114 case BufferedImage.TYPE_INT_ARGB:115 case BufferedImage.TYPE_INT_ARGB_PRE:116 redOffset = 0;117 greenOffset = 1;118 blueOffset = 2;119 alphaOffset = 3;120 break;121 default:122 Main.trace("Cannot apply color filter: Source image is of wrong type (" + type + ").");123 return src;124 }125 doFilter((DataBufferByte) srcBuffer, (DataBufferByte) destBuffer, redOffset, greenOffset, blueOffset,126 alphaOffset, src.getAlphaRaster() != null);127 return dest;128 }129 130 private void doFilter(DataBufferByte src, DataBufferByte dest, int redOffset, int greenOffset, int blueOffset,131 int alphaOffset, boolean hasAlpha) {132 byte[] srcPixels = src.getData();133 byte[] destPixels = dest.getData();134 if (srcPixels.length != destPixels.length) {135 Main.trace("Cannot apply color filter: Source/Dest lengths differ.");136 return;137 }138 int entries = hasAlpha ? 4 : 3;139 for (int i = 0; i < srcPixels.length; i += entries) {140 int r = srcPixels[i + redOffset] & 0xff;141 int g = srcPixels[i + greenOffset] & 0xff;142 int b = srcPixels[i + blueOffset] & 0xff;143 double luminosity = r * .21d + g * .72d + b * .07d;144 destPixels[i + redOffset] = mix(r, luminosity);145 destPixels[i + greenOffset] = mix(g, luminosity);146 destPixels[i + blueOffset] = mix(b, luminosity);147 if (hasAlpha) {148 destPixels[i + alphaOffset] = srcPixels[i + alphaOffset];149 }150 }151 }152 153 private byte mix(int color, double luminosity) {154 int val = (int) (colorfulness * color + (1 - colorfulness) * luminosity);155 if (val < 0) {156 return 0;157 } else if (val > 0xff) {158 return (byte) 0xff;159 } else {160 return (byte) val;161 }162 }163 164 @Override165 public Rectangle2D getBounds2D(BufferedImage src) {166 return new Rectangle(src.getWidth(), src.getHeight());167 }168 169 @Override170 public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {171 return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());172 }173 174 @Override175 public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {176 return (Point2D) srcPt.clone();177 }178 179 @Override180 public RenderingHints getRenderingHints() {181 return null;182 }183 }184 57 }
Note:
See TracChangeset
for help on using the changeset viewer.