Ticket #13222: patch-fix-13222.patch

File patch-fix-13222.patch, 10.6 KB (added by michael2402, 5 years ago)
  • src/org/openstreetmap/gui/jmapviewer/Tile.java

    diff --git a/src/org/openstreetmap/gui/jmapviewer/Tile.java b/src/org/openstreetmap/gui/jmapviewer/Tile.java
    index ba59ee0..00685f9 100644
    a b public class Tile { 
    228228    }
    229229
    230230    /**
    231      * @return tile indexes as TileXY object
     231     * @return tile indexes of the top left corner as TileXY object
    232232     */
    233233    public TileXY getTileXY() {
    234234        return new TileXY(xtile, ytile);
  • src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java b/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
    index 8faa3fc..a885172 100644
    a b import java.util.LinkedList; 
    3434import java.util.List;
    3535import java.util.Map;
    3636import java.util.Map.Entry;
     37import java.util.Objects;
    3738import java.util.Set;
    3839import java.util.concurrent.ConcurrentSkipListSet;
    3940import java.util.concurrent.atomic.AtomicInteger;
     41import java.util.function.Consumer;
     42import java.util.function.Function;
     43import java.util.stream.Collectors;
     44import java.util.stream.IntStream;
    4045import java.util.stream.Stream;
    4146
    4247import javax.swing.AbstractAction;
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    957962        return new Tile(tileSource, x, y, zoom);
    958963    }
    959964
     965    private Tile getOrCreateTile(TilePosition tilePosition) {
     966        return getOrCreateTile(tilePosition.getX(), tilePosition.getY(), tilePosition.getZoom());
     967    }
     968
    960969    private Tile getOrCreateTile(int x, int y, int zoom) {
    961970        Tile tile = getTile(x, y, zoom);
    962971        if (tile == null) {
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    970979        return tile;
    971980    }
    972981
     982    private Tile getTile(TilePosition tilePosition) {
     983        return getTile(tilePosition.getX(), tilePosition.getY(), tilePosition.getZoom());
     984    }
     985
    973986    /**
    974987     * Returns tile at given position.
    975988     * This can and will return null for tiles that are not already in the cache.
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    11261139        }
    11271140    }
    11281141
     1142    private List<Tile> paintTileImages(Graphics g, TileSet ts) {
     1143        Object paintMutex = new Object();
     1144        List<TilePosition> missed = Collections.synchronizedList(new ArrayList<>());
     1145        ts.visitTiles(tile -> {
     1146            Image img = getLoadedTileImage(tile);
     1147            if (img == null) {
     1148                missed.add(new TilePosition(tile));
     1149            }
     1150            img = applyImageProcessors((BufferedImage) img);
     1151            Rectangle2D sourceRect = coordinateConverter.getRectangleForTile(tile);
     1152            synchronized (paintMutex) {
     1153                //cannot paint in parallel
     1154                drawImageInside(g, img, sourceRect, null);
     1155            }
     1156        }, missed::add);
     1157
     1158        return missed.stream().map(this::getOrCreateTile).collect(Collectors.toList());
     1159    }
     1160
    11291161    // This function is called for several zoom levels, not just
    11301162    // the current one.  It should not trigger any tiles to be
    11311163    // downloaded.  It should also avoid polluting the tile cache
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    11371169    // border is null and we draw the entire tile set.
    11381170    private List<Tile> paintTileImages(Graphics g, TileSet ts, int zoom, Tile border) {
    11391171        if (zoom <= 0) return Collections.emptyList();
    1140         Rectangle2D borderRect = null;
    1141         if (border != null) {
    1142             borderRect = coordinateConverter.getRectangleForTile(border);
    1143         }
     1172        Rectangle2D borderRect = coordinateConverter.getRectangleForTile(border);
    11441173        List<Tile> missedTiles = new LinkedList<>();
    11451174        // The callers of this code *require* that we return any tiles
    11461175        // that we do not draw in missedTiles.  ts.allExistingTiles() by
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    12941323            int ySpan = maxY - minY + 1;
    12951324            return xSpan * ySpan;
    12961325        }
     1326
     1327        /**
     1328         * Gets a stream of all tile positions in this set
     1329         * @return A stream of all positions
     1330         */
     1331        public Stream<TilePosition> tilePositions() {
     1332            if (zoom == 0) {
     1333                return Stream.empty();
     1334            } else {
     1335                return IntStream.rangeClosed(minX, maxX).mapToObj(
     1336                        x -> IntStream.rangeClosed(minY, maxY).mapToObj(y -> new TilePosition(x, y, zoom))
     1337                        ).flatMap(Function.identity());
     1338            }
     1339        }
     1340    }
     1341
     1342    /**
     1343     * The position of a single tile.
     1344     * @author Michael Zangl
     1345     * @since xxx
     1346     */
     1347    private static class TilePosition {
     1348        private final int x;
     1349        private final int y;
     1350        private final int zoom;
     1351        public TilePosition(int x, int y, int zoom) {
     1352            super();
     1353            this.x = x;
     1354            this.y = y;
     1355            this.zoom = zoom;
     1356        }
     1357
     1358        public TilePosition(Tile tile) {
     1359            this(tile.getXtile(), tile.getYtile(), tile.getZoom());
     1360        }
     1361
     1362        /**
     1363         * @return the x position
     1364         */
     1365        public int getX() {
     1366            return x;
     1367        }
     1368
     1369        /**
     1370         * @return the y position
     1371         */
     1372        public int getY() {
     1373            return y;
     1374        }
     1375
     1376        /**
     1377         * @return the zoom
     1378         */
     1379        public int getZoom() {
     1380            return zoom;
     1381        }
     1382
     1383        @Override
     1384        public String toString() {
     1385            return "TilePosition [x=" + x + ", y=" + y + ", zoom=" + zoom + "]";
     1386        }
    12971387    }
    12981388
    12991389    private class TileSet extends TileRange {
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    13071397         * null tile set
    13081398         */
    13091399        private TileSet() {
    1310             return;
     1400            // default
    13111401        }
    13121402
    13131403        protected void sanitize() {
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    13421432         * already in the tileCache.
    13431433         */
    13441434        private List<Tile> allExistingTiles() {
    1345             return this.findAllTiles(false);
     1435            return allTiles(p -> getTile(p));
    13461436        }
    13471437
    13481438        private List<Tile> allTilesCreate() {
    1349             return this.findAllTiles(true);
     1439            return allTiles(p -> getOrCreateTile(p));
    13501440        }
    13511441
    1352         private List<Tile> findAllTiles(boolean create) {
    1353             // Tileset is either empty or too large
    1354             if (zoom == 0 || this.insane())
    1355                 return Collections.emptyList();
    1356             List<Tile> ret = new ArrayList<>();
    1357             for (int x = minX; x <= maxX; x++) {
    1358                 for (int y = minY; y <= maxY; y++) {
    1359                     Tile t;
    1360                     if (create) {
    1361                         t = getOrCreateTile(x, y, zoom);
    1362                     } else {
    1363                         t = getTile(x, y, zoom);
    1364                     }
    1365                     if (t != null) {
    1366                         ret.add(t);
    1367                     }
    1368                 }
     1442        private List<Tile> allTiles(Function<TilePosition, Tile> mapper) {
     1443            return tilePositions().map(mapper).filter(Objects::nonNull).collect(Collectors.toList());
     1444        }
     1445
     1446        @Override
     1447        public Stream<TilePosition> tilePositions() {
     1448            if (this.insane()) {
     1449                // Tileset is either empty or too large
     1450                return Stream.empty();
     1451            } else {
     1452                return super.tilePositions();
    13691453            }
    1370             return ret;
    13711454        }
    13721455
    13731456        private List<Tile> allLoadedTiles() {
    1374             List<Tile> ret = new ArrayList<>();
    1375             for (Tile t : this.allExistingTiles()) {
    1376                 if (t.isLoaded())
    1377                     ret.add(t);
    1378             }
    1379             return ret;
     1457            return allExistingTiles().stream().filter(Tile::isLoaded).collect(Collectors.toList());
    13801458        }
    13811459
    13821460        /**
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    13851463        private Comparator<Tile> getTileDistanceComparator() {
    13861464            final int centerX = (int) Math.ceil((minX + maxX) / 2d);
    13871465            final int centerY = (int) Math.ceil((minY + maxY) / 2d);
    1388             return new Comparator<Tile>() {
    1389                 private int getDistance(Tile t) {
    1390                     return Math.abs(t.getXtile() - centerX) + Math.abs(t.getYtile() - centerY);
    1391                 }
    1392 
    1393                 @Override
    1394                 public int compare(Tile o1, Tile o2) {
    1395                     int distance1 = getDistance(o1);
    1396                     int distance2 = getDistance(o2);
    1397                     return Integer.compare(distance1, distance2);
    1398                 }
    1399             };
     1466            return Comparator.comparingInt(t -> Math.abs(t.getXtile() - centerX) + Math.abs(t.getYtile() - centerY));
    14001467        }
    14011468
    14021469        private void loadAllTiles(boolean force) {
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    14191486            }
    14201487        }
    14211488
     1489        /**
     1490         * Call the given paint method for all tiles in this tile set.
     1491         * <p>
     1492         * Uses a parallel stream.
     1493         * @param visitor A visitor to call for each tile.
     1494         * @param missed a consumer to call for each missed tile.
     1495         */
     1496        public void visitTiles(Consumer<Tile> visitor, Consumer<TilePosition> missed) {
     1497            tilePositions().parallel().forEach(tp -> visitTilePosition(visitor, tp, missed));
     1498        }
     1499
     1500        private void visitTilePosition(Consumer<Tile> visitor, TilePosition tp, Consumer<TilePosition> missed) {
     1501            Tile tile = getTile(tp);
     1502            if (tile == null) {
     1503                missed.accept(tp);
     1504            } else {
     1505                visitor.accept(tile);
     1506            }
     1507        }
     1508
    14221509        @Override
    14231510        public String toString() {
    14241511            return getClass().getName() + ": zoom: " + zoom + " X(" + minX + ", " + maxX + ") Y(" + minY + ", " + maxY + ") size: " + size();
    implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeLi 
    15911678
    15921679        g.setColor(Color.DARK_GRAY);
    15931680
    1594         List<Tile> missedTiles = this.paintTileImages(g, ts, displayZoomLevel, null);
     1681        List<Tile> missedTiles = this.paintTileImages(g, ts);
    15951682        int[] otherZooms = {-1, 1, -2, 2, -3, -4, -5};
    15961683        for (int zoomOffset : otherZooms) {
    15971684            if (!getDisplaySettings().isAutoZoom()) {