--- old/src/java.desktop/share/classes/sun/awt/image/MultiResolutionToolkitImage.java 2016-09-19 19:05:02.000000000 +0400 +++ new/src/java.desktop/share/classes/sun/awt/image/MultiResolutionToolkitImage.java 2016-09-19 19:05:02.000000000 +0400 @@ -27,32 +27,51 @@ import java.awt.Image; import java.awt.image.ImageObserver; import java.awt.image.MultiResolutionImage; -import java.util.Arrays; import java.util.List; import java.util.function.Function; +import java.util.stream.Collectors; import sun.awt.SoftCache; public class MultiResolutionToolkitImage extends ToolkitImage implements MultiResolutionImage { - Image resolutionVariant; + final List resolutionVariants; - public MultiResolutionToolkitImage(Image lowResolutionImage, Image resolutionVariant) { - super(lowResolutionImage.getSource()); - this.resolutionVariant = resolutionVariant; + public MultiResolutionToolkitImage(Image baseImage, + List resolutionVariants) { + super(baseImage.getSource()); + this.resolutionVariants = resolutionVariants; } @Override public Image getResolutionVariant(double destWidth, double destHeight) { + return getResolutionVariantItem(destWidth, destHeight).getImage(); + } + + public ResolutionVariantItem getResolutionVariantItem( + double destWidth, double destHeight) { checkSize(destWidth, destHeight); - return ((destWidth <= getWidth() && destHeight <= getHeight())) - ? this : resolutionVariant; + int baseWidth = getWidth(); + int baseHeight = getHeight(); + + for (ResolutionVariantItem rvItem : resolutionVariants) { + double sx = rvItem.getScaleX(); + double sy = rvItem.getScaleY(); + if (destWidth <= baseWidth * sx && destHeight <= baseHeight * sy) { + return rvItem; + } + } + + return resolutionVariants.get(resolutionVariants.size() - 1); } public static Image map(MultiResolutionToolkitImage mrImage, Function mapper) { Image baseImage = mapper.apply(mrImage); - Image rvImage = mapper.apply(mrImage.resolutionVariant); - return new MultiResolutionToolkitImage(baseImage, rvImage); + List rvItems = mrImage.resolutionVariants.stream() + .map(new RVItemMapper(mapper)) + .collect(Collectors.toList()); + + return new MultiResolutionToolkitImage(baseImage, rvItems); } private static void checkSize(double width, double height) { @@ -67,13 +86,15 @@ } } - public Image getResolutionVariant() { - return resolutionVariant; - } - @Override public List getResolutionVariants() { - return Arrays.asList(this, resolutionVariant); + return resolutionVariants.stream() + .map(rvItem -> rvItem.getImage()) + .collect(Collectors.toList()); + } + + public List getResolutionVariantItems() { + return resolutionVariants; } private static final int BITS_INFO = ImageObserver.SOMEBITS @@ -87,23 +108,17 @@ public static ImageObserver getResolutionVariantObserver( final Image image, final ImageObserver observer, - final int imgWidth, final int imgHeight, - final int rvWidth, final int rvHeight) { - return getResolutionVariantObserver(image, observer, - imgWidth, imgHeight, rvWidth, rvHeight, false); - } - - public static ImageObserver getResolutionVariantObserver( - final Image image, final ImageObserver observer, - final int imgWidth, final int imgHeight, - final int rvWidth, final int rvHeight, boolean concatenateInfo) { + final double scaleX, final double scaleY, + boolean concatenateInfo) { if (observer == null) { return null; } synchronized (ObserverCache.INSTANCE) { - ImageObserver o = (ImageObserver) ObserverCache.INSTANCE.get(observer); + + Object key = new ObserverKey(observer, scaleX, scaleY); + ImageObserver o = (ImageObserver) ObserverCache.INSTANCE.get(key); if (o == null) { @@ -111,16 +126,16 @@ int x, int y, int width, int height) -> { if ((flags & (ImageObserver.WIDTH | BITS_INFO)) != 0) { - width = (width + 1) / 2; + width = (int) Math.ceil(width / scaleX); } if ((flags & (ImageObserver.HEIGHT | BITS_INFO)) != 0) { - height = (height + 1) / 2; + height = (int) Math.ceil(height / scaleY); } if ((flags & BITS_INFO) != 0) { - x /= 2; - y /= 2; + x = (int) Math.floor(x / scaleX); + y = (int) Math.floor(y / scaleY); } if(concatenateInfo){ @@ -132,9 +147,91 @@ image, flags, x, y, width, height); }; - ObserverCache.INSTANCE.put(observer, o); + ObserverCache.INSTANCE.put(key, o); } return o; } } -} + + public static class ResolutionVariantItem { + + final Image image; + final double scaleX; + final double scaleY; + + public ResolutionVariantItem(Image image, double scaleX, double scaleY) { + this.image = image; + this.scaleX = scaleX; + this.scaleY = scaleY; + } + + public Image getImage() { + return image; + } + + public double getScaleX() { + return scaleX; + } + + public double getScaleY() { + return scaleY; + } + + public ResolutionVariantItem map(Function mapper) { + return new ResolutionVariantItem(mapper.apply(image), scaleX, scaleY); + } + } + + static class RVItemMapper + implements Function { + + final Function mapper; + + public RVItemMapper(Function mapper) { + this.mapper = mapper; + } + + @Override + public ResolutionVariantItem apply(ResolutionVariantItem rvItem) { + return new ResolutionVariantItem(mapper.apply(rvItem.getImage()), + rvItem.getScaleX(), rvItem.getScaleY()); + } + } + + static class ObserverKey { + + final ImageObserver observer; + final double scaleX; + final double scaleY; + + public ObserverKey(ImageObserver observer, double scaleX, double scaleY) { + this.observer = observer; + this.scaleX = scaleX; + this.scaleY = scaleY; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof ObserverKey)) { + return false; + } + + ObserverKey observerKey = (ObserverKey) obj; + return scaleX == observerKey.scaleX + && scaleY == observerKey.scaleY + && observer.equals(observerKey.observer); + } + + @Override + public int hashCode() { + int hash = observer.hashCode(); + hash = 31 * hash + Double.hashCode(scaleX); + hash = 31 * hash + Double.hashCode(scaleY); + return hash; + } + } +} \ No newline at end of file