Changeset 14284 in josm
- Timestamp:
- 2018-09-30T20:11:41+02:00 (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
r14238 r14284 34 34 import java.util.Base64; 35 35 import java.util.Collection; 36 import java.util.Collections;37 36 import java.util.HashMap; 38 37 import java.util.HashSet; … … 271 270 } 272 271 273 /** small cache of critical images used in many parts of the application */274 private static final Map<OsmPrimitiveType, ImageIcon> osmPrimitiveTypeCache = Collections.synchronizedMap(new HashMap<>());275 276 272 /** directories in which images are searched */ 277 273 protected Collection<String> dirs; … … 317 313 private static final Map<Image, Map<Long, Image>> ROTATE_CACHE = new HashMap<>(); 318 314 315 /** small cache of critical images used in many parts of the application */ 316 private static final Map<OsmPrimitiveType, ImageIcon> osmPrimitiveTypeCache = new HashMap<>(); 317 318 /** larger cache of critical padded image icons used in many parts of the application */ 319 private static final Map<Dimension, Map<MapImage, ImageIcon>> paddedImageCache = new HashMap<>(); 320 319 321 private static final ExecutorService IMAGE_FETCHER = 320 322 Executors.newSingleThreadExecutor(Utils.newThreadFactory("image-fetcher-%d", Thread.NORM_PRIORITY)); … … 834 836 835 837 /** 836 * Clears the internal image cache .838 * Clears the internal image caches. 837 839 * @since 11021 838 840 */ … … 840 842 synchronized (cache) { 841 843 cache.clear(); 844 } 845 synchronized (ROTATE_CACHE) { 846 ROTATE_CACHE.clear(); 847 } 848 synchronized (paddedImageCache) { 849 paddedImageCache.clear(); 850 } 851 synchronized (osmPrimitiveTypeCache) { 852 osmPrimitiveTypeCache.clear(); 842 853 } 843 854 } … … 1478 1489 public static ImageIcon get(OsmPrimitiveType type) { 1479 1490 CheckParameterUtil.ensureParameterNotNull(type, "type"); 1480 return osmPrimitiveTypeCache.computeIfAbsent(type, t -> get("data", t.getAPIName())); 1491 synchronized (osmPrimitiveTypeCache) { 1492 return osmPrimitiveTypeCache.computeIfAbsent(type, t -> get("data", t.getAPIName())); 1493 } 1481 1494 } 1482 1495 … … 1490 1503 // Check if the current styles have special icon for tagged objects. 1491 1504 if (primitive.isTagged()) { 1492 Pair<StyleElementList, Range> nodeStyles; 1493 DataSet ds = primitive.getDataSet(); 1494 if (ds != null) { 1495 ds.getReadLock().lock(); 1496 } 1497 try { 1498 nodeStyles = MapPaintStyles.getStyles().generateStyles(primitive, 100, false); 1499 } finally { 1500 if (ds != null) { 1501 ds.getReadLock().unlock(); 1502 } 1503 } 1504 for (StyleElement style : nodeStyles.a) { 1505 if (style instanceof NodeElement) { 1506 NodeElement nodeStyle = (NodeElement) style; 1507 MapImage icon = nodeStyle.mapImage; 1508 if (icon != null) { 1509 int backgroundRealWidth = GuiSizesHelper.getSizeDpiAdjusted(iconSize.width); 1510 int backgroundRealHeight = GuiSizesHelper.getSizeDpiAdjusted(iconSize.height); 1511 int iconRealWidth = icon.getWidth(); 1512 int iconRealHeight = icon.getHeight(); 1513 BufferedImage image = new BufferedImage(backgroundRealWidth, backgroundRealHeight, 1514 BufferedImage.TYPE_INT_ARGB); 1515 double scaleFactor = Math.min(backgroundRealWidth / (double) iconRealWidth, backgroundRealHeight 1516 / (double) iconRealHeight); 1517 Image iconImage = icon.getImage(false); 1518 Image scaledIcon; 1519 final int scaledWidth; 1520 final int scaledHeight; 1521 if (scaleFactor < 1) { 1522 // Scale icon such that it fits on background. 1523 scaledWidth = (int) (iconRealWidth * scaleFactor); 1524 scaledHeight = (int) (iconRealHeight * scaleFactor); 1525 scaledIcon = iconImage.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH); 1526 } else { 1527 // Use original size, don't upscale. 1528 scaledWidth = iconRealWidth; 1529 scaledHeight = iconRealHeight; 1530 scaledIcon = iconImage; 1531 } 1532 image.getGraphics().drawImage(scaledIcon, (backgroundRealWidth - scaledWidth) / 2, 1533 (backgroundRealHeight - scaledHeight) / 2, null); 1534 1535 return new ImageIcon(image); 1536 } 1537 } 1505 ImageIcon icon = getTaggedPadded(primitive, iconSize); 1506 if (icon != null) { 1507 return icon; 1538 1508 } 1539 1509 } … … 1556 1526 // Use generic default icon. 1557 1527 return ImageProvider.get(primitive.getDisplayType()); 1528 } 1529 1530 /** 1531 * Computes a new padded icon for the given tagged primitive, using map paint styles. 1532 * This is a slow operation. 1533 * @param primitive tagged OSM primitive 1534 * @param iconSize icon size in pixels 1535 * @return a new padded icon for the given tagged primitive, or null 1536 */ 1537 private static ImageIcon getTaggedPadded(OsmPrimitive primitive, Dimension iconSize) { 1538 Pair<StyleElementList, Range> nodeStyles; 1539 DataSet ds = primitive.getDataSet(); 1540 if (ds != null) { 1541 ds.getReadLock().lock(); 1542 } 1543 try { 1544 nodeStyles = MapPaintStyles.getStyles().generateStyles(primitive, 100, false); 1545 } finally { 1546 if (ds != null) { 1547 ds.getReadLock().unlock(); 1548 } 1549 } 1550 for (StyleElement style : nodeStyles.a) { 1551 if (style instanceof NodeElement) { 1552 NodeElement nodeStyle = (NodeElement) style; 1553 MapImage icon = nodeStyle.mapImage; 1554 if (icon != null) { 1555 return getPaddedIcon(icon, iconSize); 1556 } 1557 } 1558 } 1559 return null; 1560 } 1561 1562 /** 1563 * Returns an {@link ImageIcon} for the given map image, at the specified size. 1564 * Uses a cache to improve performance. 1565 * @param mapImage map image 1566 * @param iconSize size in pixels 1567 * @return an {@code ImageIcon} for the given map image, at the specified size 1568 * @see #clearCache 1569 * @since 14284 1570 */ 1571 public static ImageIcon getPaddedIcon(MapImage mapImage, Dimension iconSize) { 1572 synchronized (paddedImageCache) { 1573 return paddedImageCache.computeIfAbsent(iconSize, x -> new HashMap<>()).computeIfAbsent(mapImage, icon -> { 1574 int backgroundRealWidth = GuiSizesHelper.getSizeDpiAdjusted(iconSize.width); 1575 int backgroundRealHeight = GuiSizesHelper.getSizeDpiAdjusted(iconSize.height); 1576 int iconRealWidth = icon.getWidth(); 1577 int iconRealHeight = icon.getHeight(); 1578 BufferedImage image = new BufferedImage(backgroundRealWidth, backgroundRealHeight, BufferedImage.TYPE_INT_ARGB); 1579 double scaleFactor = Math.min( 1580 backgroundRealWidth / (double) iconRealWidth, 1581 backgroundRealHeight / (double) iconRealHeight); 1582 Image iconImage = icon.getImage(false); 1583 Image scaledIcon; 1584 final int scaledWidth; 1585 final int scaledHeight; 1586 if (scaleFactor < 1) { 1587 // Scale icon such that it fits on background. 1588 scaledWidth = (int) (iconRealWidth * scaleFactor); 1589 scaledHeight = (int) (iconRealHeight * scaleFactor); 1590 scaledIcon = iconImage.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH); 1591 } else { 1592 // Use original size, don't upscale. 1593 scaledWidth = iconRealWidth; 1594 scaledHeight = iconRealHeight; 1595 scaledIcon = iconImage; 1596 } 1597 image.getGraphics().drawImage(scaledIcon, 1598 (backgroundRealWidth - scaledWidth) / 2, 1599 (backgroundRealHeight - scaledHeight) / 2, null); 1600 1601 return new ImageIcon(image); 1602 }); 1603 } 1558 1604 } 1559 1605
Note:
See TracChangeset
for help on using the changeset viewer.