src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java

Print this page

        

@@ -24,48 +24,112 @@
  */
 package sun.awt.image;
 
 import java.awt.Image;
 import java.awt.Graphics;
+import java.awt.geom.Dimension2D;
 import java.awt.image.BufferedImage;
 import java.util.Arrays;
 import java.util.List;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 
 public class MultiResolutionBufferedImage extends BufferedImage
         implements MultiResolutionImage {
 
-    Image[] resolutionVariants;
-    int baseIndex;
+    private final MultiResolutionImageMapper mapper;
+    private final Dimension2D[] sizes;
 
-    public MultiResolutionBufferedImage(int imageType, int baseIndex, Image... images) {
-        super(images[baseIndex].getWidth(null), images[baseIndex].getHeight(null),
-                imageType);
-        this.baseIndex = baseIndex;
-        this.resolutionVariants = images;
+    public MultiResolutionBufferedImage(Image baseImage,
+            Dimension2D[] sizes, MultiResolutionImageMapper mapper) {
+        super(baseImage.getWidth(null), baseImage.getHeight(null),
+                BufferedImage.TYPE_INT_ARGB_PRE);
+        this.sizes = sizes;
+        this.mapper = mapper;
         Graphics g = getGraphics();
-        g.drawImage(images[baseIndex], 0, 0, null);
+        g.drawImage(baseImage, 0, 0, null);
         g.dispose();
-        images[baseIndex] = this;
     }
 
     @Override
     public Image getResolutionVariant(int width, int height) {
-        for (Image image : resolutionVariants) {
-            if (width <= image.getWidth(null) && height <= image.getHeight(null)) {
-                return image;
+        int baseWidth = getWidth();
+        int baseHeight = getHeight();
+
+        if (baseWidth == width && baseHeight == height) {
+            return this;
             }
+
+        ImageCache cache = ImageCache.getInstance();
+        ImageCacheKey key = new ImageCacheKey(this, width, height);
+        Image resolutionVariant = cache.getImage(key);
+        if (resolutionVariant == null) {
+            resolutionVariant = mapper.apply(width, height);
+            cache.setImage(key, resolutionVariant);
         }
-        return this;
+
+        return resolutionVariant;
     }
 
     @Override
     public List<Image> getResolutionVariants() {
-        return Arrays.asList(resolutionVariants);
+        return Arrays.stream(sizes).map((Function<Dimension2D, Image>) size
+                -> getResolutionVariant((int) size.getWidth(),
+                        (int) size.getHeight())).collect(Collectors.toList());
     }
 
     public MultiResolutionBufferedImage map(Function<Image, Image> mapper) {
-        return new MultiResolutionBufferedImage(getType(), baseIndex,
-                Arrays.stream(resolutionVariants).map(mapper)
-                        .toArray(length -> new Image[length]));
+        return new MultiResolutionBufferedImage(mapper.apply(this), sizes,
+                (width, height) ->
+                        mapper.apply(getResolutionVariant(width, height)));
+    }
+
+    public interface MultiResolutionImageMapper {
+
+        Image apply(int width, int height);
+    }
+
+    private static class ImageCacheKey implements ImageCache.PixelsKey {
+
+        private final int pixelCount;
+        private final int hash;
+
+        private final int w;
+        private final int h;
+        private final Image baseImage;
+
+        ImageCacheKey(final Image baseImage,
+                final int w, final int h) {
+            this.baseImage = baseImage;
+            this.w = w;
+            this.h = h;
+            this.pixelCount = w * h;
+            hash = hash();
+        }
+
+        @Override
+        public int getPixelCount() {
+            return pixelCount;
+        }
+
+        private int hash() {
+            int hash = baseImage.hashCode();
+            hash = 31 * hash + w;
+            hash = 31 * hash + h;
+            return hash;
+        }
+
+        @Override
+        public int hashCode() {
+            return hash;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ImageCacheKey) {
+                ImageCacheKey key = (ImageCacheKey) obj;
+                return baseImage == key.baseImage && w == key.w && h == key.h;
+            }
+            return false;
+        }
     }
 }