8029339: Custom MultiResolution image support on HiDPI displays
Reviewed-by: flar, serb
This commit is contained in:
parent
e1ca4d3a94
commit
e643aeb178
@ -46,7 +46,7 @@ import com.apple.laf.AquaIcon.JRSUIControlSpec;
|
||||
import com.apple.laf.AquaIcon.SystemIcon;
|
||||
import com.apple.laf.AquaUtils.RecyclableObject;
|
||||
import com.apple.laf.AquaUtils.RecyclableSingleton;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import sun.awt.image.MultiResolutionCachedImage;
|
||||
|
||||
public class AquaImageFactory {
|
||||
|
@ -31,7 +31,7 @@ import java.awt.image.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import sun.awt.image.MultiResolutionCachedImage;
|
||||
|
||||
import sun.awt.image.SunWritableRaster;
|
||||
|
@ -954,6 +954,64 @@ public class RenderingHints
|
||||
public static final Object VALUE_STROKE_PURE =
|
||||
SunHints.VALUE_STROKE_PURE;
|
||||
|
||||
/**
|
||||
* Image resolution variant hint key.
|
||||
* The {@code RESOLUTION_VARIANT} hint controls which image resolution
|
||||
* variant should be chosen for image drawing.
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #VALUE_RESOLUTION_VARIANT_DEFAULT}
|
||||
* <li>{@link #VALUE_RESOLUTION_VARIANT_BASE}
|
||||
* <li>{@link #VALUE_RESOLUTION_VARIANT_SIZE_FIT}
|
||||
* <li>{@link #VALUE_RESOLUTION_VARIANT_DPI_FIT}
|
||||
* </ul>
|
||||
* @since 1.9
|
||||
*/
|
||||
public static final Key KEY_RESOLUTION_VARIANT =
|
||||
SunHints.KEY_RESOLUTION_VARIANT;
|
||||
|
||||
/**
|
||||
* Image resolution variant hint value -- an image resolution variant is
|
||||
* chosen based on a default heuristic which may depend on the policies
|
||||
* of the platform
|
||||
*
|
||||
* @see #KEY_RESOLUTION_VARIANT
|
||||
* @since 1.9
|
||||
*/
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_DEFAULT =
|
||||
SunHints.VALUE_RESOLUTION_VARIANT_DEFAULT;
|
||||
|
||||
/**
|
||||
* Image resolution variant hint value -- the standard resolution of an image
|
||||
* is always used.
|
||||
*
|
||||
* @see #KEY_RESOLUTION_VARIANT
|
||||
* @since 1.9
|
||||
*/
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_BASE =
|
||||
SunHints.VALUE_RESOLUTION_VARIANT_BASE;
|
||||
|
||||
/**
|
||||
* Image resolution variant hint value -- an image resolution variant is
|
||||
* chosen based on the DPI of the screen and the transform in the Graphics2D
|
||||
* context.
|
||||
*
|
||||
* @see #KEY_RESOLUTION_VARIANT
|
||||
* @since 1.9
|
||||
*/
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_SIZE_FIT =
|
||||
SunHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT;
|
||||
|
||||
/**
|
||||
* Image resolution variant hint value -- an image resolution variant is
|
||||
* chosen based only on the DPI of the screen.
|
||||
*
|
||||
* @see #KEY_RESOLUTION_VARIANT
|
||||
* @since 1.9
|
||||
*/
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_DPI_FIT =
|
||||
SunHints.VALUE_RESOLUTION_VARIANT_DPI_FIT;
|
||||
|
||||
/**
|
||||
* Constructs a new object with keys and values initialized
|
||||
* from the specified Map object which may be null.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,50 +22,39 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.awt.image;
|
||||
package java.awt.image;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* This class provides default implementations for the
|
||||
* <code>MultiResolutionImage</code> interface. The developer needs only
|
||||
* to subclass this abstract class and define the <code>getResolutionVariant</code>,
|
||||
* <code>getResolutionVariants</code>, and <code>getBaseImage</code> methods.
|
||||
*
|
||||
* This class provides default implementations of several {@code Image} methods
|
||||
* for classes that want to implement the {@MultiResolutionImage} interface.
|
||||
*
|
||||
* For example,
|
||||
* {@code
|
||||
* <pre> {@code
|
||||
* public class CustomMultiResolutionImage extends AbstractMultiResolutionImage {
|
||||
*
|
||||
* int baseImageIndex;
|
||||
* Image[] resolutionVariants;
|
||||
* final Image[] resolutionVariants;
|
||||
*
|
||||
* public CustomMultiResolutionImage(int baseImageIndex,
|
||||
* Image... resolutionVariants) {
|
||||
* this.baseImageIndex = baseImageIndex;
|
||||
* public CustomMultiResolutionImage(Image... resolutionVariants) {
|
||||
* this.resolutionVariants = resolutionVariants;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public Image getResolutionVariant(float logicalDPIX, float logicalDPIY,
|
||||
* float baseImageWidth, float baseImageHeight,
|
||||
* float destImageWidth, float destImageHeight) {
|
||||
* // return a resolution variant based on the given logical DPI,
|
||||
* // base image size, or destination image size
|
||||
* public Image getResolutionVariant(
|
||||
* double destImageWidth, double destImageHeight) {
|
||||
* // return a resolution variant based on the given destination image size
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public List<Image> getResolutionVariants() {
|
||||
* return Arrays.asList(resolutionVariants);
|
||||
* return Collections.unmodifiableList(Arrays.asList(resolutionVariants));
|
||||
* }
|
||||
*
|
||||
* protected Image getBaseImage() {
|
||||
* return resolutionVariants[baseImageIndex];
|
||||
* return resolutionVariants[0];
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* } </pre>
|
||||
*
|
||||
* @see java.awt.Image
|
||||
* @see java.awt.image.MultiResolutionImage
|
||||
@ -75,49 +64,39 @@ import java.awt.image.*;
|
||||
public abstract class AbstractMultiResolutionImage extends java.awt.Image
|
||||
implements MultiResolutionImage {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int getWidth(ImageObserver observer) {
|
||||
return getBaseImage().getWidth(null);
|
||||
return getBaseImage().getWidth(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int getHeight(ImageObserver observer) {
|
||||
return getBaseImage().getHeight(null);
|
||||
return getBaseImage().getHeight(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public ImageProducer getSource() {
|
||||
return getBaseImage().getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Graphics getGraphics() {
|
||||
return getBaseImage().getGraphics();
|
||||
|
||||
throw new UnsupportedOperationException("getGraphics() not supported"
|
||||
+ " on Multi-Resolution Images");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Object getProperty(String name, ImageObserver observer) {
|
||||
return getBaseImage().getProperty(name, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return base image
|
||||
* Return the base image representing the best version of the image for
|
||||
* rendering at the default width and height.
|
||||
*
|
||||
* @return the base image of the set of multi-resolution images
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
protected abstract Image getBaseImage();
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.awt.image;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class is an array-based implementation of
|
||||
* the {@code AbstractMultiResolutionImage} class.
|
||||
*
|
||||
* This class will implement the
|
||||
* {@code getResolutionVariant(double destImageWidth, double destImageHeight)}
|
||||
* method using a simple algorithm which will return the first image variant
|
||||
* in the array that is large enough to satisfy the rendering request. The
|
||||
* last image in the array will be returned if no suitable image is found
|
||||
* that is as large as the rendering request.
|
||||
* <p>
|
||||
* For best effect the array of images should be sorted with each image being
|
||||
* both wider and taller than the previous image. The base image need not be
|
||||
* the first image in the array. No exception will be thrown if the images
|
||||
* are not sorted as suggested.
|
||||
*
|
||||
* @see java.awt.Image
|
||||
* @see java.awt.image.MultiResolutionImage
|
||||
* @see java.awt.image.AbstractMultiResolutionImage
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public class BaseMultiResolutionImage extends AbstractMultiResolutionImage {
|
||||
|
||||
private final int baseImageIndex;
|
||||
private final Image[] resolutionVariants;
|
||||
|
||||
/**
|
||||
* Creates a multi-resolution image with the given resolution variants.
|
||||
* The first resolution variant is used as the base image.
|
||||
*
|
||||
* @param resolutionVariants array of resolution variants sorted by image size
|
||||
* @throws IllegalArgumentException if null or zero-length array is passed
|
||||
* @throws NullPointerException if the specified {@code resolutionVariants}
|
||||
* contains one or more null elements
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public BaseMultiResolutionImage(Image... resolutionVariants) {
|
||||
this(0, resolutionVariants);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a multi-resolution image with the given base image index and
|
||||
* resolution variants.
|
||||
*
|
||||
* @param baseImageIndex the index of base image in the resolution variants
|
||||
* array
|
||||
* @param resolutionVariants array of resolution variants sorted by image size
|
||||
* @throws IllegalArgumentException if null or zero-length array is passed
|
||||
* @throws NullPointerException if the specified {@code resolutionVariants}
|
||||
* contains one or more null elements
|
||||
* @throws IndexOutOfBoundsException if {@code baseImageIndex} is
|
||||
* negative or greater than or equal to {@code resolutionVariants}
|
||||
* length.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public BaseMultiResolutionImage(int baseImageIndex,
|
||||
Image... resolutionVariants) {
|
||||
|
||||
if (resolutionVariants == null || resolutionVariants.length == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Null or zero-length array is passed");
|
||||
}
|
||||
|
||||
if (baseImageIndex < 0 || baseImageIndex >= resolutionVariants.length) {
|
||||
throw new IndexOutOfBoundsException("Invalid base image index: "
|
||||
+ baseImageIndex);
|
||||
}
|
||||
|
||||
this.baseImageIndex = baseImageIndex;
|
||||
this.resolutionVariants = Arrays.copyOf(resolutionVariants,
|
||||
resolutionVariants.length);
|
||||
|
||||
for (Image resolutionVariant : this.resolutionVariants) {
|
||||
Objects.requireNonNull(resolutionVariant,
|
||||
"Resolution variant can't be null");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(double destImageWidth,
|
||||
double destImageHeight) {
|
||||
|
||||
checkSize(destImageWidth, destImageHeight);
|
||||
|
||||
for (Image rvImage : resolutionVariants) {
|
||||
if (destImageWidth <= rvImage.getWidth(null)
|
||||
&& destImageHeight <= rvImage.getHeight(null)) {
|
||||
return rvImage;
|
||||
}
|
||||
}
|
||||
return resolutionVariants[resolutionVariants.length - 1];
|
||||
}
|
||||
|
||||
private static void checkSize(double width, double height) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Width (%s) or height (%s) cannot be <= 0", width, height));
|
||||
}
|
||||
|
||||
if (!Double.isFinite(width) || !Double.isFinite(height)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Width (%s) or height (%s) is not finite", width, height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getResolutionVariants() {
|
||||
return Collections.unmodifiableList(Arrays.asList(resolutionVariants));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Image getBaseImage() {
|
||||
return resolutionVariants[baseImageIndex];
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.awt.image;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This interface is designed to be an optional additional API supported by
|
||||
* some implementations of {@link java.awt.Image} to allow them to provide
|
||||
* alternate images for various rendering resolutions. The various
|
||||
* {@code Graphics.drawImage(...)} variant methods will consult the methods
|
||||
* of this interface if it is implemented on the argument {@code Image} object
|
||||
* in order to choose the best representation to use for each rendering operation.
|
||||
* <p>
|
||||
* The {@code MultiResolutionImage} interface should be implemented by any
|
||||
* subclass of {@code java.awt.Image} whose instances are intended to provide
|
||||
* image resolution variants according to the given image width and height.
|
||||
* For convenience, toolkit images obtained from
|
||||
* {@code Toolkit.getImage(String name)} and {@code Toolkit.getImage(URL url)}
|
||||
* will implement this interface on platforms that support naming conventions
|
||||
* for resolution variants of stored image media and the
|
||||
* {@code AbstractMultiResolutionImage} and {@code BaseMultiResolutionImage}
|
||||
* classes are provided to facilitate easy construction of custom multi-resolution
|
||||
* images from a list of related images.
|
||||
*
|
||||
* @see java.awt.Image
|
||||
* @see java.awt.image.AbstractMultiResolutionImage
|
||||
* @see java.awt.image.BaseMultiResolutionImage
|
||||
* @see java.awt.Toolkit#getImage(java.lang.String filename)
|
||||
* @see java.awt.Toolkit#getImage(java.net.URL url)
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
public interface MultiResolutionImage {
|
||||
|
||||
/**
|
||||
* Gets a specific image that is the best variant to represent
|
||||
* this logical image at the indicated size.
|
||||
*
|
||||
* @param destImageWidth the width of the destination image, in pixels.
|
||||
* @param destImageHeight the height of the destination image, in pixels.
|
||||
* @return image resolution variant.
|
||||
* @throws IllegalArgumentException if {@code destImageWidth} or
|
||||
* {@code destImageHeight} is less than or equal to zero, infinity,
|
||||
* or NaN.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
Image getResolutionVariant(double destImageWidth, double destImageHeight);
|
||||
|
||||
/**
|
||||
* Gets a readable list of all resolution variants.
|
||||
* The list must be nonempty and contain at least one resolution variant.
|
||||
* <p>
|
||||
* Note that many implementations might return an unmodifiable list.
|
||||
* <p>
|
||||
* @return list of resolution variants.
|
||||
* @since 1.9
|
||||
*/
|
||||
public List<Image> getResolutionVariants();
|
||||
}
|
@ -257,8 +257,10 @@ public class SunHints {
|
||||
*/
|
||||
@Native public static final int INTKEY_RESOLUTION_VARIANT = 9;
|
||||
@Native public static final int INTVAL_RESOLUTION_VARIANT_DEFAULT = 0;
|
||||
@Native public static final int INTVAL_RESOLUTION_VARIANT_OFF = 1;
|
||||
@Native public static final int INTVAL_RESOLUTION_VARIANT_ON = 2;
|
||||
@Native public static final int INTVAL_RESOLUTION_VARIANT_BASE = 1;
|
||||
@Native public static final int INTVAL_RESOLUTION_VARIANT_SIZE_FIT = 2;
|
||||
@Native public static final int INTVAL_RESOLUTION_VARIANT_DPI_FIT = 3;
|
||||
|
||||
/**
|
||||
* LCD text contrast control hint key.
|
||||
* Value is "100" to make discontiguous with the others which
|
||||
@ -466,15 +468,23 @@ public class SunHints {
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_DEFAULT =
|
||||
new SunHints.Value(KEY_RESOLUTION_VARIANT,
|
||||
SunHints.INTVAL_RESOLUTION_VARIANT_DEFAULT,
|
||||
"Choose image resolutions based on a default heuristic");
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_OFF =
|
||||
"Choose image resolutions based on a default"
|
||||
+ "heuristic");
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_BASE =
|
||||
new SunHints.Value(KEY_RESOLUTION_VARIANT,
|
||||
SunHints.INTVAL_RESOLUTION_VARIANT_OFF,
|
||||
SunHints.INTVAL_RESOLUTION_VARIANT_BASE,
|
||||
"Use only the standard resolution of an image");
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_ON =
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_SIZE_FIT =
|
||||
new SunHints.Value(KEY_RESOLUTION_VARIANT,
|
||||
SunHints.INTVAL_RESOLUTION_VARIANT_ON,
|
||||
"Always use resolution-specific variants of images");
|
||||
SunHints.INTVAL_RESOLUTION_VARIANT_SIZE_FIT,
|
||||
"Choose image resolutions based on the DPI"
|
||||
+ "of the screen and transform"
|
||||
+ "in the Graphics2D context");
|
||||
public static final Object VALUE_RESOLUTION_VARIANT_DPI_FIT =
|
||||
new SunHints.Value(KEY_RESOLUTION_VARIANT,
|
||||
SunHints.INTVAL_RESOLUTION_VARIANT_DPI_FIT,
|
||||
"Choose image resolutions based only on the DPI"
|
||||
+ " of the screen");
|
||||
|
||||
public static class LCDContrastKey extends Key {
|
||||
|
||||
|
@ -60,7 +60,7 @@ import sun.awt.im.InputContext;
|
||||
import sun.awt.image.ByteArrayImageSource;
|
||||
import sun.awt.image.FileImageSource;
|
||||
import sun.awt.image.ImageRepresentation;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import sun.awt.image.MultiResolutionToolkitImage;
|
||||
import sun.awt.image.ToolkitImage;
|
||||
import sun.awt.image.URLImageSource;
|
||||
|
@ -33,6 +33,7 @@ import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
import java.awt.image.AbstractMultiResolutionImage;
|
||||
|
||||
public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
|
||||
@ -58,7 +59,10 @@ public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(int width, int height) {
|
||||
public Image getResolutionVariant(double destWidth, double destHeight) {
|
||||
checkSize(destWidth, destHeight);
|
||||
int width = (int) Math.ceil(destWidth);
|
||||
int height = (int) Math.ceil(destHeight);
|
||||
ImageCache cache = ImageCache.getInstance();
|
||||
ImageCacheKey key = new ImageCacheKey(this, width, height);
|
||||
Image resolutionVariant = cache.getImage(key);
|
||||
@ -70,11 +74,23 @@ public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
return resolutionVariant;
|
||||
}
|
||||
|
||||
private static void checkSize(double width, double height) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Width (%s) or height (%s) cannot be <= 0", width, height));
|
||||
}
|
||||
|
||||
if (!Double.isFinite(width) || !Double.isFinite(height)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Width (%s) or height (%s) is not finite", width, height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getResolutionVariants() {
|
||||
return Arrays.stream(sizes).map((Function<Dimension2D, Image>) size
|
||||
-> getResolutionVariant((int) size.getWidth(),
|
||||
(int) size.getHeight())).collect(Collectors.toList());
|
||||
-> getResolutionVariant(size.getWidth(), size.getHeight()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public MultiResolutionCachedImage map(Function<Image, Image> mapper) {
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.awt.image;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This interface is designed to provide a set of images at various resolutions.
|
||||
*
|
||||
* The <code>MultiResolutionImage</code> interface should be implemented by any
|
||||
* class whose instances are intended to provide image resolution variants
|
||||
* according to the given image width and height.
|
||||
*
|
||||
* For example,
|
||||
* <pre>
|
||||
* {@code
|
||||
* public class ScaledImage extends BufferedImage
|
||||
* implements MultiResolutionImage {
|
||||
*
|
||||
* @Override
|
||||
* public Image getResolutionVariant(int width, int height) {
|
||||
* return ((width <= getWidth() && height <= getHeight()))
|
||||
* ? this : highResolutionImage;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public List<Image> getResolutionVariants() {
|
||||
* return Arrays.asList(this, highResolutionImage);
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* It is recommended to cache image variants for performance reasons.
|
||||
*
|
||||
* <b>WARNING</b>: This class is an implementation detail. This API may change
|
||||
* between update release, and it may even be removed or be moved in some other
|
||||
* package(s)/class(es).
|
||||
*/
|
||||
public interface MultiResolutionImage {
|
||||
|
||||
/**
|
||||
* Provides an image with necessary resolution which best fits to the given
|
||||
* image width and height.
|
||||
*
|
||||
* @param width the desired image resolution width.
|
||||
* @param height the desired image resolution height.
|
||||
* @return image resolution variant.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public Image getResolutionVariant(int width, int height);
|
||||
|
||||
/**
|
||||
* Gets list of all resolution variants including the base image
|
||||
*
|
||||
* @return list of resolution variants.
|
||||
* @since 1.8
|
||||
*/
|
||||
public List<Image> getResolutionVariants();
|
||||
}
|
@ -26,6 +26,7 @@ package sun.awt.image;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import sun.misc.SoftCache;
|
||||
@ -40,11 +41,24 @@ public class MultiResolutionToolkitImage extends ToolkitImage implements MultiRe
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(int width, int height) {
|
||||
return ((width <= getWidth() && height <= getHeight()))
|
||||
public Image getResolutionVariant(double destWidth, double destHeight) {
|
||||
checkSize(destWidth, destHeight);
|
||||
return ((destWidth <= getWidth() && destHeight <= getHeight()))
|
||||
? this : resolutionVariant;
|
||||
}
|
||||
|
||||
private static void checkSize(double width, double height) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Width (%s) or height (%s) cannot be <= 0", width, height));
|
||||
}
|
||||
|
||||
if (!Double.isFinite(width) || !Double.isFinite(height)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Width (%s) or height (%s) is not finite", width, height));
|
||||
}
|
||||
}
|
||||
|
||||
public Image getResolutionVariant() {
|
||||
return resolutionVariant;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ import java.util.Iterator;
|
||||
import sun.misc.PerformanceLogger;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
|
||||
import static java.awt.geom.AffineTransform.TYPE_FLIP;
|
||||
import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE;
|
||||
@ -3087,9 +3087,8 @@ public final class SunGraphics2D
|
||||
// end of text rendering methods
|
||||
|
||||
private boolean isHiDPIImage(final Image img) {
|
||||
return (SurfaceManager.getImageScale(img) != 1) ||
|
||||
(resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_OFF
|
||||
&& img instanceof MultiResolutionImage);
|
||||
return (SurfaceManager.getImageScale(img) != 1)
|
||||
|| img instanceof MultiResolutionImage;
|
||||
}
|
||||
|
||||
private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
|
||||
@ -3175,24 +3174,41 @@ public final class SunGraphics2D
|
||||
int type = transform.getType();
|
||||
int dw = dx2 - dx1;
|
||||
int dh = dy2 - dy1;
|
||||
double destRegionWidth;
|
||||
double destRegionHeight;
|
||||
|
||||
if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP)) == 0) {
|
||||
destRegionWidth = dw;
|
||||
destRegionHeight = dh;
|
||||
} else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
|
||||
destRegionWidth = dw * transform.getScaleX();
|
||||
destRegionHeight = dh * transform.getScaleY();
|
||||
double destImageWidth;
|
||||
double destImageHeight;
|
||||
|
||||
if (resolutionVariantHint == SunHints.INTVAL_RESOLUTION_VARIANT_BASE) {
|
||||
destImageWidth = srcWidth;
|
||||
destImageHeight = srcHeight;
|
||||
} else if (resolutionVariantHint == SunHints.INTVAL_RESOLUTION_VARIANT_DPI_FIT) {
|
||||
AffineTransform configTransform = getDefaultTransform();
|
||||
if (configTransform.isIdentity()) {
|
||||
destImageWidth = srcWidth;
|
||||
destImageHeight = srcHeight;
|
||||
} else {
|
||||
destImageWidth = srcWidth * configTransform.getScaleX();
|
||||
destImageHeight = srcHeight * configTransform.getScaleY();
|
||||
}
|
||||
} else {
|
||||
destRegionWidth = dw * Math.hypot(
|
||||
transform.getScaleX(), transform.getShearY());
|
||||
destRegionHeight = dh * Math.hypot(
|
||||
transform.getShearX(), transform.getScaleY());
|
||||
}
|
||||
double destRegionWidth;
|
||||
double destRegionHeight;
|
||||
|
||||
int destImageWidth = (int) Math.abs(srcWidth * destRegionWidth / sw);
|
||||
int destImageHeight = (int) Math.abs(srcHeight * destRegionHeight / sh);
|
||||
if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP)) == 0) {
|
||||
destRegionWidth = dw;
|
||||
destRegionHeight = dh;
|
||||
} else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
|
||||
destRegionWidth = dw * transform.getScaleX();
|
||||
destRegionHeight = dh * transform.getScaleY();
|
||||
} else {
|
||||
destRegionWidth = dw * Math.hypot(
|
||||
transform.getScaleX(), transform.getShearY());
|
||||
destRegionHeight = dh * Math.hypot(
|
||||
transform.getShearX(), transform.getScaleY());
|
||||
}
|
||||
destImageWidth = Math.abs(srcWidth * destRegionWidth / sw);
|
||||
destImageHeight = Math.abs(srcHeight * destRegionHeight / sh);
|
||||
}
|
||||
|
||||
Image resolutionVariant
|
||||
= img.getResolutionVariant(destImageWidth, destImageHeight);
|
||||
|
@ -25,19 +25,16 @@ import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Label;
|
||||
import java.awt.Point;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.BaseMultiResolutionImage;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.swing.JApplet;
|
||||
import jdk.testlibrary.OSInfo;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -52,7 +49,7 @@ import sun.awt.image.MultiResolutionImage;
|
||||
public class MultiResolutionCursorTest extends JApplet {
|
||||
//Declare things used in the test, like buttons and labels here
|
||||
|
||||
static final int sizes[] = {16, 32, 128};
|
||||
static final int sizes[] = {8, 16, 32, 128};
|
||||
static final Color colors[] = {Color.WHITE, Color.RED, Color.GREEN, Color.BLUE};
|
||||
|
||||
public void init() {
|
||||
@ -87,7 +84,12 @@ public class MultiResolutionCursorTest extends JApplet {
|
||||
setVisible(true);
|
||||
validate();
|
||||
|
||||
final Image image = new MultiResolutionCursor();
|
||||
final Image image = new BaseMultiResolutionImage(
|
||||
createResolutionVariant(0),
|
||||
createResolutionVariant(1),
|
||||
createResolutionVariant(2),
|
||||
createResolutionVariant(3)
|
||||
);
|
||||
|
||||
int center = sizes[0] / 2;
|
||||
Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor(
|
||||
@ -101,53 +103,14 @@ public class MultiResolutionCursorTest extends JApplet {
|
||||
frame.setVisible(true);
|
||||
}// start()
|
||||
|
||||
|
||||
static class MultiResolutionCursor extends BufferedImage implements MultiResolutionImage {
|
||||
|
||||
List<Image> highResolutionImages;
|
||||
|
||||
public MultiResolutionCursor() {
|
||||
super(sizes[0], sizes[0], BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
draw(getGraphics(), 0);
|
||||
highResolutionImages = new LinkedList<>();
|
||||
highResolutionImages.add(this);
|
||||
|
||||
for (int i = 1; i < sizes.length; i++) {
|
||||
BufferedImage highResolutionImage =
|
||||
new BufferedImage(sizes[i], sizes[i], BufferedImage.TYPE_INT_RGB);
|
||||
draw(highResolutionImage.getGraphics(), i);
|
||||
highResolutionImages.add(highResolutionImage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(int width, int height) {
|
||||
|
||||
for (int i = 0; i < sizes.length; i++) {
|
||||
Image image = highResolutionImages.get(i);
|
||||
int w = image.getWidth(null);
|
||||
int h = image.getHeight(null);
|
||||
|
||||
if (width <= w && height <= h) {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
return highResolutionImages.get(highResolutionImages.size() - 1);
|
||||
}
|
||||
|
||||
void draw(Graphics graphics, int index) {
|
||||
Graphics2D g2 = (Graphics2D) graphics;
|
||||
Color color = colors[index];
|
||||
g2.setColor(color);
|
||||
g2.fillRect(0, 0, sizes[index], sizes[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Image> getResolutionVariants() {
|
||||
return highResolutionImages;
|
||||
}
|
||||
static BufferedImage createResolutionVariant(int i) {
|
||||
BufferedImage resolutionVariant = new BufferedImage(sizes[i], sizes[i],
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2 = resolutionVariant.createGraphics();
|
||||
g2.setColor(colors[i]);
|
||||
g2.fillRect(0, 0, sizes[i], sizes[i]);
|
||||
g2.dispose();
|
||||
return resolutionVariant;
|
||||
}
|
||||
}// class BlockedWindowTest
|
||||
|
||||
|
@ -23,15 +23,17 @@
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.Toolkit;
|
||||
import sun.awt.OSInfo;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import jdk.testlibrary.OSInfo;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8033534 8035069
|
||||
* @summary [macosx] Get MultiResolution image from native system
|
||||
* @author Alexander Scherbatiy
|
||||
* @modules java.desktop/sun.awt
|
||||
* java.desktop/sun.awt.image
|
||||
* @modules java.desktop/sun.awt.image
|
||||
* @library /lib/testlibrary
|
||||
* @build jdk.testlibrary.OSInfo
|
||||
* @run main NSImageToMultiResolutionImageTest
|
||||
*/
|
||||
|
||||
|
@ -25,12 +25,13 @@ import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import sun.awt.SunHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
|
||||
/**
|
||||
* @test @bug 8011059
|
||||
@ -173,8 +174,9 @@ public class MultiResolutionImageCommonTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(int width, int height) {
|
||||
return ((width <= getWidth() && height <= getHeight()))
|
||||
public Image getResolutionVariant(
|
||||
double destImageWidth, double destImageHeight) {
|
||||
return ((destImageWidth <= getWidth() && destImageHeight <= getHeight()))
|
||||
? this : highResolutionImage;
|
||||
}
|
||||
|
||||
@ -187,8 +189,8 @@ public class MultiResolutionImageCommonTest {
|
||||
static void setImageScalingHint(
|
||||
Graphics2D g2d, boolean enableImageScaling) {
|
||||
g2d.setRenderingHint(SunHints.KEY_RESOLUTION_VARIANT, enableImageScaling
|
||||
? SunHints.VALUE_RESOLUTION_VARIANT_ON
|
||||
: SunHints.VALUE_RESOLUTION_VARIANT_OFF);
|
||||
? RenderingHints.VALUE_RESOLUTION_VARIANT_DEFAULT
|
||||
: RenderingHints.VALUE_RESOLUTION_VARIANT_BASE);
|
||||
}
|
||||
|
||||
static void checkColor(int rgb, boolean isImageScaled) {
|
||||
|
@ -33,10 +33,11 @@ import java.net.URL;
|
||||
import javax.imageio.ImageIO;
|
||||
import sun.awt.SunHints;
|
||||
import java.awt.MediaTracker;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.ImageObserver;
|
||||
import javax.swing.JPanel;
|
||||
import jdk.testlibrary.Platform;
|
||||
import sun.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
|
||||
/**
|
||||
* @test @bug 8011059
|
||||
@ -339,8 +340,8 @@ public class MultiResolutionImageTest {
|
||||
static void setImageScalingHint(Graphics2D g2d,
|
||||
boolean enableImageScaling) {
|
||||
g2d.setRenderingHint(SunHints.KEY_RESOLUTION_VARIANT, enableImageScaling
|
||||
? SunHints.VALUE_RESOLUTION_VARIANT_ON
|
||||
: SunHints.VALUE_RESOLUTION_VARIANT_OFF);
|
||||
? RenderingHints.VALUE_RESOLUTION_VARIANT_DEFAULT
|
||||
: RenderingHints.VALUE_RESOLUTION_VARIANT_BASE);
|
||||
}
|
||||
|
||||
static void checkColor(int rgb, boolean isImageScaled) {
|
||||
|
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BaseMultiResolutionImage;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8029339
|
||||
* @author Alexander Scherbatiy
|
||||
* @summary Custom MultiResolution image support on HiDPI displays
|
||||
* @run main BaseMultiResolutionImageTest
|
||||
*/
|
||||
public class BaseMultiResolutionImageTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
testZeroRVIMages();
|
||||
testNullRVIMages();
|
||||
testNullRVIMage();
|
||||
testIOOBException();
|
||||
testRVSizes();
|
||||
testBaseMRImage();
|
||||
}
|
||||
|
||||
static void testZeroRVIMages() {
|
||||
try {
|
||||
new BaseMultiResolutionImage();
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("IllegalArgumentException is not thrown!");
|
||||
}
|
||||
|
||||
static void testNullRVIMages() {
|
||||
try {
|
||||
new BaseMultiResolutionImage(null);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("IllegalArgumentException is not thrown!");
|
||||
}
|
||||
|
||||
static void testNullRVIMage() {
|
||||
|
||||
Image baseImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
try {
|
||||
new BaseMultiResolutionImage(baseImage, null);
|
||||
} catch (NullPointerException ignored) {
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("NullPointerException is not thrown!");
|
||||
}
|
||||
|
||||
static void testIOOBException() {
|
||||
|
||||
for (int baseImageIndex : new int[]{-3, 2, 4}) {
|
||||
try {
|
||||
new BaseMultiResolutionImage(baseImageIndex,
|
||||
createRVImage(0), createRVImage(1));
|
||||
} catch (IndexOutOfBoundsException ignored) {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new RuntimeException("IndexOutOfBoundsException is not thrown!");
|
||||
}
|
||||
}
|
||||
|
||||
static void testRVSizes() {
|
||||
|
||||
int imageSize = getSize(1);
|
||||
|
||||
double[][] sizeArray = {
|
||||
{-imageSize, imageSize},
|
||||
{2 * imageSize, -2 * imageSize},
|
||||
{Double.POSITIVE_INFINITY, imageSize},
|
||||
{Double.POSITIVE_INFINITY, -imageSize},
|
||||
{imageSize, Double.NEGATIVE_INFINITY},
|
||||
{-imageSize, Double.NEGATIVE_INFINITY},
|
||||
{Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY},
|
||||
{Double.NaN, imageSize},
|
||||
{imageSize, Double.NaN},
|
||||
{Double.NaN, Double.NaN},
|
||||
{Double.POSITIVE_INFINITY, Double.NaN}
|
||||
};
|
||||
|
||||
for (double[] sizes : sizeArray) {
|
||||
try {
|
||||
MultiResolutionImage mrImage = new BaseMultiResolutionImage(
|
||||
0, createRVImage(0), createRVImage(1));
|
||||
mrImage.getResolutionVariant(sizes[0], sizes[1]);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new RuntimeException("IllegalArgumentException is not thrown!");
|
||||
}
|
||||
}
|
||||
|
||||
static void testBaseMRImage() {
|
||||
int baseIndex = 1;
|
||||
int length = 3;
|
||||
BufferedImage[] resolutionVariants = new BufferedImage[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
resolutionVariants[i] = createRVImage(i);
|
||||
}
|
||||
|
||||
BaseMultiResolutionImage mrImage = new BaseMultiResolutionImage(baseIndex,
|
||||
resolutionVariants);
|
||||
|
||||
List<Image> rvImageList = mrImage.getResolutionVariants();
|
||||
if (rvImageList.size() != length) {
|
||||
throw new RuntimeException("Wrong size of resolution variants list!");
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
int imageSize = getSize(i);
|
||||
Image testRVImage = mrImage.getResolutionVariant(imageSize, imageSize);
|
||||
|
||||
if (testRVImage != resolutionVariants[i]) {
|
||||
throw new RuntimeException("Wrong resolution variant!");
|
||||
}
|
||||
|
||||
if (rvImageList.get(i) != resolutionVariants[i]) {
|
||||
throw new RuntimeException("Wrong resolution variant!");
|
||||
}
|
||||
}
|
||||
|
||||
BufferedImage baseImage = resolutionVariants[baseIndex];
|
||||
|
||||
if (baseImage.getWidth() != mrImage.getWidth(null)
|
||||
|| baseImage.getHeight() != mrImage.getHeight(null)) {
|
||||
throw new RuntimeException("Base image is wrong!");
|
||||
}
|
||||
|
||||
boolean passed = false;
|
||||
|
||||
try {
|
||||
rvImageList.set(0, createRVImage(10));
|
||||
} catch (Exception e) {
|
||||
passed = true;
|
||||
}
|
||||
|
||||
if (!passed) {
|
||||
throw new RuntimeException("Resolution variants list is modifiable!");
|
||||
}
|
||||
|
||||
passed = false;
|
||||
|
||||
try {
|
||||
rvImageList.remove(0);
|
||||
} catch (Exception e) {
|
||||
passed = true;
|
||||
}
|
||||
|
||||
if (!passed) {
|
||||
throw new RuntimeException("Resolution variants list is modifiable!");
|
||||
}
|
||||
|
||||
passed = false;
|
||||
|
||||
try {
|
||||
rvImageList.add(0, createRVImage(10));
|
||||
} catch (Exception e) {
|
||||
passed = true;
|
||||
}
|
||||
|
||||
if (!passed) {
|
||||
throw new RuntimeException("Resolution variants list is modifiable!");
|
||||
}
|
||||
}
|
||||
|
||||
private static int getSize(int i) {
|
||||
return 8 * (i + 1);
|
||||
}
|
||||
|
||||
private static BufferedImage createRVImage(int i) {
|
||||
return new BufferedImage(getSize(i), getSize(i),
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
}
|
@ -98,7 +98,7 @@ public class MultiResolutionCachedImageTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(int width, int height) {
|
||||
public Image getResolutionVariant(double width, double height) {
|
||||
if (width == size || height == size) {
|
||||
throw new RuntimeException("Base image is requested!");
|
||||
}
|
||||
|
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BaseMultiResolutionImage;
|
||||
import static java.awt.RenderingHints.KEY_RESOLUTION_VARIANT;
|
||||
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_BASE;
|
||||
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_DPI_FIT;
|
||||
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT;
|
||||
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_DEFAULT;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import sun.java2d.StateTrackable;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8029339
|
||||
* @author Alexander Scherbatiy
|
||||
* @summary Custom MultiResolution image support on HiDPI displays
|
||||
* @modules java.desktop/sun.java2d
|
||||
* @run main MultiResolutionRenderingHintsTest
|
||||
*/
|
||||
public class MultiResolutionRenderingHintsTest {
|
||||
|
||||
private static final int BASE_SIZE = 200;
|
||||
private static final Color[] COLORS = {
|
||||
Color.CYAN, Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED, Color.PINK
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
int length = COLORS.length;
|
||||
BufferedImage[] resolutionVariants = new BufferedImage[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
resolutionVariants[i] = createRVImage(getSize(i), COLORS[i]);
|
||||
}
|
||||
|
||||
BaseMultiResolutionImage mrImage = new BaseMultiResolutionImage(
|
||||
resolutionVariants);
|
||||
|
||||
// base
|
||||
Color color = getImageColor(VALUE_RESOLUTION_VARIANT_BASE, mrImage, 2, 3);
|
||||
if (!getColorForScale(1).equals(color)) {
|
||||
throw new RuntimeException("Wrong base resolution variant!");
|
||||
}
|
||||
|
||||
// dpi fit
|
||||
color = getImageColor(VALUE_RESOLUTION_VARIANT_DPI_FIT, mrImage, 2, 3);
|
||||
if (!getColorForScale(2).equals(color)) {
|
||||
throw new RuntimeException("Resolution variant is not based on dpi!");
|
||||
}
|
||||
|
||||
// size fit
|
||||
color = getImageColor(VALUE_RESOLUTION_VARIANT_SIZE_FIT, mrImage, 2, 3);
|
||||
if (!getColorForScale(6).equals(color)) {
|
||||
throw new RuntimeException("Resolution variant is not based on"
|
||||
+ " rendered size!");
|
||||
}
|
||||
|
||||
// default
|
||||
// depends on the policies of the platform
|
||||
// just check that exception is not thrown
|
||||
getImageColor(VALUE_RESOLUTION_VARIANT_DEFAULT, mrImage, 2, 3);
|
||||
}
|
||||
|
||||
private static Color getColorForScale(int scale) {
|
||||
return COLORS[scale - 1];
|
||||
}
|
||||
|
||||
private static Color getImageColor(final Object renderingHint, Image image,
|
||||
double configScale, double graphicsScale) {
|
||||
|
||||
int width = image.getWidth(null);
|
||||
int height = image.getHeight(null);
|
||||
|
||||
TestSurfaceData surface = new TestSurfaceData(width, height, configScale);
|
||||
SunGraphics2D g2d = new SunGraphics2D(surface,
|
||||
Color.BLACK, Color.BLACK, null);
|
||||
g2d.setRenderingHint(KEY_RESOLUTION_VARIANT, renderingHint);
|
||||
g2d.scale(graphicsScale, graphicsScale);
|
||||
g2d.drawImage(image, 0, 0, null);
|
||||
g2d.dispose();
|
||||
return surface.getColor(width / 2, height / 2);
|
||||
}
|
||||
|
||||
private static int getSize(int i) {
|
||||
return (i + 1) * BASE_SIZE;
|
||||
}
|
||||
|
||||
private static BufferedImage createRVImage(int size, Color color) {
|
||||
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = image.createGraphics();
|
||||
g.setColor(Color.BLACK);
|
||||
g.fillRect(0, 0, size, size);
|
||||
g.setColor(color);
|
||||
g.fillOval(0, 0, size, size);
|
||||
g.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
static class TestGraphicsConfig extends GraphicsConfiguration {
|
||||
|
||||
private final double scale;
|
||||
|
||||
TestGraphicsConfig(double scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsDevice getDevice() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel(int transparency) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getDefaultTransform() {
|
||||
return AffineTransform.getScaleInstance(scale, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getNormalizingTransform() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
|
||||
static class TestSurfaceData extends SurfaceData {
|
||||
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final GraphicsConfiguration gc;
|
||||
private final BufferedImage buffImage;
|
||||
private final double scale;
|
||||
|
||||
public TestSurfaceData(int width, int height, double scale) {
|
||||
super(StateTrackable.State.DYNAMIC, SurfaceType.Custom, ColorModel.getRGBdefault());
|
||||
this.scale = scale;
|
||||
gc = new TestGraphicsConfig(scale);
|
||||
this.width = (int) Math.ceil(scale * width);
|
||||
this.height = (int) Math.ceil(scale * height);
|
||||
buffImage = new BufferedImage(this.width, this.height,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
Color getColor(int x, int y) {
|
||||
int sx = (int) Math.ceil(x * scale);
|
||||
int sy = (int) Math.ceil(y * scale);
|
||||
return new Color(buffImage.getRGB(sx, sy));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData getReplacement() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return gc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Raster getRaster(int x, int y, int w, int h) {
|
||||
return buffImage.getRaster();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle(0, 0, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDestination() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user