提交 0be06f1c 编写于 作者: A alexsch

8011059: [macosx] Support automatic @2x images loading on Mac OS X

Reviewed-by: serb, flar
上级 a8304d97
......@@ -35,14 +35,17 @@ import java.awt.event.KeyEvent;
import java.awt.im.InputMethodHighlight;
import java.awt.peer.*;
import java.lang.reflect.*;
import java.net.URL;
import java.security.*;
import java.util.*;
import java.util.concurrent.Callable;
import java.net.MalformedURLException;
import sun.awt.*;
import sun.lwawt.*;
import sun.lwawt.LWWindowPeer.PeerType;
import sun.security.action.GetBooleanAction;
import sun.awt.image.MultiResolutionImage;
import sun.util.CoreResourceBundleControl;
......@@ -489,9 +492,30 @@ public final class LWCToolkit extends LWToolkit {
@Override
public Image getImage(final String filename) {
final Image nsImage = checkForNSImage(filename);
if (nsImage != null) return nsImage;
if (nsImage != null) {
return nsImage;
}
if (imageCached(filename)) {
return super.getImage(filename);
}
return super.getImage(filename);
String fileneame2x = getScaledImageName(filename);
return (imageExists(fileneame2x))
? getImageWithResolutionVariant(filename, fileneame2x)
: super.getImage(filename);
}
@Override
public Image getImage(URL url) {
if (imageCached(url)) {
return super.getImage(url);
}
URL url2x = getScaledImageURL(url);
return (imageExists(url2x))
? getImageWithResolutionVariant(url, url2x) : super.getImage(url);
}
static final String nsImagePrefix = "NSImage://";
......@@ -781,4 +805,36 @@ public final class LWCToolkit extends LWToolkit {
public boolean enableInputMethodsForTextComponent() {
return true;
}
private static URL getScaledImageURL(URL url) {
try {
String scaledImagePath = getScaledImageName(url.getPath());
return scaledImagePath == null ? null : new URL(url.getProtocol(),
url.getHost(), url.getPort(), scaledImagePath);
} catch (MalformedURLException e) {
return null;
}
}
private static String getScaledImageName(String path) {
if (!isValidPath(path)) {
return null;
}
int slash = path.lastIndexOf('/');
String name = (slash < 0) ? path : path.substring(slash + 1);
if (name.contains("@2x")) {
return null;
}
int dot = name.lastIndexOf('.');
String name2x = (dot < 0) ? name + "@2x"
: name.substring(0, dot) + "@2x" + name.substring(dot);
return (slash < 0) ? name2x : path.substring(0, slash + 1) + name2x;
}
private static boolean isValidPath(String path) {
return !path.isEmpty() && !path.endsWith("/") && !path.endsWith(".");
}
}
......@@ -28,6 +28,7 @@ package java.awt;
import java.awt.Component;
import java.awt.Image;
import java.awt.image.ImageObserver;
import sun.awt.image.MultiResolutionToolkitImage;
/**
* The <code>MediaTracker</code> class is a utility class to track
......@@ -222,10 +223,17 @@ public class MediaTracker implements java.io.Serializable {
* @param h the height at which the image is rendered
*/
public synchronized void addImage(Image image, int id, int w, int h) {
addImageImpl(image, id, w, h);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
addImageImpl(rvImage, id, 2 * w, 2 * h);
}
}
private void addImageImpl(Image image, int id, int w, int h) {
head = MediaEntry.insert(head,
new ImageMediaEntry(this, image, id, w, h));
}
/**
* Flag indicating that media is currently being loaded.
* @see java.awt.MediaTracker#statusAll
......@@ -719,6 +727,15 @@ public class MediaTracker implements java.io.Serializable {
* @since JDK1.1
*/
public synchronized void removeImage(Image image) {
removeImageImpl(image);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
removeImageImpl(rvImage);
}
notifyAll(); // Notify in case remaining images are "done".
}
private void removeImageImpl(Image image) {
MediaEntry cur = head;
MediaEntry prev = null;
while (cur != null) {
......@@ -735,7 +752,6 @@ public class MediaTracker implements java.io.Serializable {
}
cur = next;
}
notifyAll(); // Notify in case remaining images are "done".
}
/**
......@@ -750,6 +766,15 @@ public class MediaTracker implements java.io.Serializable {
* @since JDK1.1
*/
public synchronized void removeImage(Image image, int id) {
removeImageImpl(image, id);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
removeImageImpl(rvImage, id);
}
notifyAll(); // Notify in case remaining images are "done".
}
private void removeImageImpl(Image image, int id) {
MediaEntry cur = head;
MediaEntry prev = null;
while (cur != null) {
......@@ -766,7 +791,6 @@ public class MediaTracker implements java.io.Serializable {
}
cur = next;
}
notifyAll(); // Notify in case remaining images are "done".
}
/**
......@@ -783,6 +807,16 @@ public class MediaTracker implements java.io.Serializable {
*/
public synchronized void removeImage(Image image, int id,
int width, int height) {
removeImageImpl(image, id, width, height);
Image rvImage = getResolutionVariant(image);
if (rvImage != null) {
removeImageImpl(rvImage, id, 2 * width, 2 * height);
}
notifyAll(); // Notify in case remaining images are "done".
}
private void removeImageImpl(Image image, int id, int width, int height) {
MediaEntry cur = head;
MediaEntry prev = null;
while (cur != null) {
......@@ -801,12 +835,18 @@ public class MediaTracker implements java.io.Serializable {
}
cur = next;
}
notifyAll(); // Notify in case remaining images are "done".
}
synchronized void setDone() {
notifyAll();
}
private static Image getResolutionVariant(Image image) {
if (image instanceof MultiResolutionToolkitImage) {
return ((MultiResolutionToolkitImage) image).getResolutionVariant();
}
return null;
}
}
abstract class MediaEntry {
......
......@@ -172,7 +172,7 @@ public class SunHints {
}
}
private static final int NUM_KEYS = 9;
private static final int NUM_KEYS = 10;
private static final int VALS_PER_KEY = 8;
/**
......@@ -252,6 +252,13 @@ public class SunHints {
@Native public static final int INTVAL_STROKE_NORMALIZE = 1;
@Native public static final int INTVAL_STROKE_PURE = 2;
/**
* Image scaling hint key and values
*/
@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;
/**
* LCD text contrast control hint key.
* Value is "100" to make discontiguous with the others which
......@@ -450,6 +457,24 @@ public class SunHints {
SunHints.INTVAL_STROKE_PURE,
"Pure stroke conversion for accurate paths");
/**
* Image resolution variant hint key and value objects
*/
public static final Key KEY_RESOLUTION_VARIANT =
new SunHints.Key(SunHints.INTKEY_RESOLUTION_VARIANT,
"Global image resolution variant key");
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 =
new SunHints.Value(KEY_RESOLUTION_VARIANT,
SunHints.INTVAL_RESOLUTION_VARIANT_OFF,
"Use only the standard resolution of an image");
public static final Object VALUE_RESOLUTION_VARIANT_ON =
new SunHints.Value(KEY_RESOLUTION_VARIANT,
SunHints.INTVAL_RESOLUTION_VARIANT_ON,
"Always use resolution-specific variants of images");
public static class LCDContrastKey extends Key {
......
......@@ -36,6 +36,9 @@ import java.awt.image.*;
import java.awt.TrayIcon;
import java.awt.SystemTray;
import java.awt.event.InputEvent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.concurrent.TimeUnit;
......@@ -715,33 +718,7 @@ public abstract class SunToolkit extends Toolkit
static final SoftCache imgCache = new SoftCache();
static Image getImageFromHash(Toolkit tk, URL url) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
java.security.Permission perm =
url.openConnection().getPermission();
if (perm != null) {
try {
sm.checkPermission(perm);
} catch (SecurityException se) {
// fallback to checkRead/checkConnect for pre 1.2
// security managers
if ((perm instanceof java.io.FilePermission) &&
perm.getActions().indexOf("read") != -1) {
sm.checkRead(perm.getName());
} else if ((perm instanceof
java.net.SocketPermission) &&
perm.getActions().indexOf("connect") != -1) {
sm.checkConnect(url.getHost(), url.getPort());
} else {
throw se;
}
}
}
} catch (java.io.IOException ioe) {
sm.checkConnect(url.getHost(), url.getPort());
}
}
checkPermissions(url);
synchronized (imgCache) {
Image img = (Image)imgCache.get(url);
if (img == null) {
......@@ -757,10 +734,7 @@ public abstract class SunToolkit extends Toolkit
static Image getImageFromHash(Toolkit tk,
String filename) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(filename);
}
checkPermissions(filename);
synchronized (imgCache) {
Image img = (Image)imgCache.get(filename);
if (img == null) {
......@@ -782,42 +756,42 @@ public abstract class SunToolkit extends Toolkit
return getImageFromHash(this, url);
}
public Image createImage(String filename) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(filename);
protected Image getImageWithResolutionVariant(String fileName,
String resolutionVariantName) {
synchronized (imgCache) {
Image image = getImageFromHash(this, fileName);
if (image instanceof MultiResolutionImage) {
return image;
}
Image resolutionVariant = getImageFromHash(this, resolutionVariantName);
image = createImageWithResolutionVariant(image, resolutionVariant);
imgCache.put(fileName, image);
return image;
}
return createImage(new FileImageSource(filename));
}
public Image createImage(URL url) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
java.security.Permission perm =
url.openConnection().getPermission();
if (perm != null) {
try {
sm.checkPermission(perm);
} catch (SecurityException se) {
// fallback to checkRead/checkConnect for pre 1.2
// security managers
if ((perm instanceof java.io.FilePermission) &&
perm.getActions().indexOf("read") != -1) {
sm.checkRead(perm.getName());
} else if ((perm instanceof
java.net.SocketPermission) &&
perm.getActions().indexOf("connect") != -1) {
sm.checkConnect(url.getHost(), url.getPort());
} else {
throw se;
}
}
}
} catch (java.io.IOException ioe) {
sm.checkConnect(url.getHost(), url.getPort());
protected Image getImageWithResolutionVariant(URL url,
URL resolutionVariantURL) {
synchronized (imgCache) {
Image image = getImageFromHash(this, url);
if (image instanceof MultiResolutionImage) {
return image;
}
Image resolutionVariant = getImageFromHash(this, resolutionVariantURL);
image = createImageWithResolutionVariant(image, resolutionVariant);
imgCache.put(url, image);
return image;
}
}
public Image createImage(String filename) {
checkPermissions(filename);
return createImage(new FileImageSource(filename));
}
public Image createImage(URL url) {
checkPermissions(url);
return createImage(new URLImageSource(url));
}
......@@ -829,6 +803,11 @@ public abstract class SunToolkit extends Toolkit
return new ToolkitImage(producer);
}
public static Image createImageWithResolutionVariant(Image image,
Image resolutionVariant) {
return new MultiResolutionToolkitImage(image, resolutionVariant);
}
public int checkImage(Image img, int w, int h, ImageObserver o) {
if (!(img instanceof ToolkitImage)) {
return ImageObserver.ALLBITS;
......@@ -841,7 +820,7 @@ public abstract class SunToolkit extends Toolkit
} else {
repbits = tkimg.getImageRep().check(o);
}
return tkimg.check(o) | repbits;
return (tkimg.check(o) | repbits) & checkResolutionVariant(img, w, h, o);
}
public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
......@@ -863,7 +842,97 @@ public abstract class SunToolkit extends Toolkit
return false;
}
ImageRepresentation ir = tkimg.getImageRep();
return ir.prepare(o);
return ir.prepare(o) & prepareResolutionVariant(img, w, h, o);
}
private int checkResolutionVariant(Image img, int w, int h, ImageObserver o) {
ToolkitImage rvImage = getResolutionVariant(img);
// Ignore the resolution variant in case of error
return (rvImage == null || rvImage.hasError()) ? 0xFFFF :
checkImage(rvImage, 2 * w, 2 * h, MultiResolutionToolkitImage.
getResolutionVariantObserver(
img, o, w, h, 2 * w, 2 * h));
}
private boolean prepareResolutionVariant(Image img, int w, int h,
ImageObserver o) {
ToolkitImage rvImage = getResolutionVariant(img);
// Ignore the resolution variant in case of error
return rvImage == null || rvImage.hasError() || prepareImage(
rvImage, 2 * w, 2 * h,
MultiResolutionToolkitImage.getResolutionVariantObserver(
img, o, w, h, 2 * w, 2 * h));
}
private static ToolkitImage getResolutionVariant(Image image) {
if (image instanceof MultiResolutionToolkitImage) {
Image resolutionVariant = ((MultiResolutionToolkitImage) image).
getResolutionVariant();
if (resolutionVariant instanceof ToolkitImage) {
return (ToolkitImage) resolutionVariant;
}
}
return null;
}
protected static boolean imageCached(Object key) {
return imgCache.containsKey(key);
}
protected static boolean imageExists(String filename) {
checkPermissions(filename);
return filename != null && new File(filename).exists();
}
@SuppressWarnings("try")
protected static boolean imageExists(URL url) {
checkPermissions(url);
if (url != null) {
try (InputStream is = url.openStream()) {
return true;
}catch(IOException e){
return false;
}
}
return false;
}
private static void checkPermissions(String filename) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(filename);
}
}
private static void checkPermissions(URL url) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
java.security.Permission perm =
url.openConnection().getPermission();
if (perm != null) {
try {
sm.checkPermission(perm);
} catch (SecurityException se) {
// fallback to checkRead/checkConnect for pre 1.2
// security managers
if ((perm instanceof java.io.FilePermission) &&
perm.getActions().indexOf("read") != -1) {
sm.checkRead(perm.getName());
} else if ((perm instanceof
java.net.SocketPermission) &&
perm.getActions().indexOf("connect") != -1) {
sm.checkConnect(url.getHost(), url.getPort());
} else {
throw se;
}
}
}
} catch (java.io.IOException ioe) {
sm.checkConnect(url.getHost(), url.getPort());
}
}
}
/**
......
/*
* 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 JDK1.8
*/
public Image getResolutionVariant(int width, int height);
/**
* Gets list of all resolution variants including the base image
*
* @return list of resolution variants.
* @since JDK1.8
*/
public List<Image> getResolutionVariants();
}
/*
* 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.awt.image.ImageObserver;
import java.util.Arrays;
import java.util.List;
import sun.misc.SoftCache;
public class MultiResolutionToolkitImage extends ToolkitImage implements MultiResolutionImage {
Image resolutionVariant;
public MultiResolutionToolkitImage(Image lowResolutionImage, Image resolutionVariant) {
super(lowResolutionImage.getSource());
this.resolutionVariant = resolutionVariant;
}
@Override
public Image getResolutionVariant(int width, int height) {
return ((width <= getWidth() && height <= getHeight()))
? this : resolutionVariant;
}
public Image getResolutionVariant() {
return resolutionVariant;
}
@Override
public List<Image> getResolutionVariants() {
return Arrays.<Image>asList(this, resolutionVariant);
}
private static final int BITS_INFO = ImageObserver.SOMEBITS
| ImageObserver.FRAMEBITS | ImageObserver.ALLBITS;
private static class ObserverCache {
static final SoftCache INSTANCE = new SoftCache();
}
public static ImageObserver getResolutionVariantObserver(
final Image image, final ImageObserver observer,
final int imgWidth, final int imgHeight,
final int rvWidth, final int rvHeight) {
if (observer == null) {
return null;
}
synchronized (ObserverCache.INSTANCE) {
ImageObserver o = (ImageObserver) ObserverCache.INSTANCE.get(image);
if (o == null) {
o = (Image resolutionVariant, int flags,
int x, int y, int width, int height) -> {
if ((flags & (ImageObserver.WIDTH | BITS_INFO)) != 0) {
width = (width + 1) / 2;
}
if ((flags & (ImageObserver.HEIGHT | BITS_INFO)) != 0) {
height = (height + 1) / 2;
}
if ((flags & BITS_INFO) != 0) {
x /= 2;
y /= 2;
}
return observer.imageUpdate(
image, flags, x, y, width, height);
};
ObserverCache.INSTANCE.put(image, o);
}
return o;
}
}
}
......@@ -61,6 +61,7 @@ import java.awt.FontMetrics;
import java.awt.Rectangle;
import java.text.AttributedCharacterIterator;
import java.awt.Font;
import java.awt.Point;
import java.awt.image.ImageObserver;
import java.awt.Transparency;
import java.awt.font.GlyphVector;
......@@ -93,6 +94,13 @@ import java.util.Iterator;
import sun.misc.PerformanceLogger;
import java.lang.annotation.Native;
import sun.awt.image.MultiResolutionImage;
import static java.awt.geom.AffineTransform.TYPE_FLIP;
import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE;
import static java.awt.geom.AffineTransform.TYPE_TRANSLATION;
import sun.awt.image.MultiResolutionToolkitImage;
import sun.awt.image.ToolkitImage;
/**
* This is a the master Graphics2D superclass for all of the Sun
......@@ -237,6 +245,7 @@ public final class SunGraphics2D
protected Region devClip; // Actual physical drawable in pixels
private final int devScale; // Actual physical scale factor
private int resolutionVariantHint;
// cached state for text rendering
private boolean validFontInfo;
......@@ -274,6 +283,7 @@ public final class SunGraphics2D
lcdTextContrast = lcdTextContrastDefaultValue;
interpolationHint = -1;
strokeHint = SunHints.INTVAL_STROKE_DEFAULT;
resolutionVariantHint = SunHints.INTVAL_RESOLUTION_VARIANT_DEFAULT;
interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR;
......@@ -1249,6 +1259,10 @@ public final class SunGraphics2D
stateChanged = (strokeHint != newHint);
strokeHint = newHint;
break;
case SunHints.INTKEY_RESOLUTION_VARIANT:
stateChanged = (resolutionVariantHint != newHint);
resolutionVariantHint = newHint;
break;
default:
recognized = false;
stateChanged = false;
......@@ -1322,6 +1336,9 @@ public final class SunGraphics2D
case SunHints.INTKEY_STROKE_CONTROL:
return SunHints.Value.get(SunHints.INTKEY_STROKE_CONTROL,
strokeHint);
case SunHints.INTKEY_RESOLUTION_VARIANT:
return SunHints.Value.get(SunHints.INTKEY_RESOLUTION_VARIANT,
resolutionVariantHint);
}
return null;
}
......@@ -3050,18 +3067,58 @@ public final class SunGraphics2D
}
// end of text rendering methods
private static boolean isHiDPIImage(final Image img) {
return SurfaceManager.getImageScale(img) != 1;
private boolean isHiDPIImage(final Image img) {
return (SurfaceManager.getImageScale(img) != 1) ||
(resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_OFF
&& img instanceof MultiResolutionImage);
}
private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
int dy2, int sx1, int sy1, int sx2, int sy2,
Color bgcolor, ImageObserver observer) {
final int scale = SurfaceManager.getImageScale(img);
sx1 = Region.clipScale(sx1, scale);
sx2 = Region.clipScale(sx2, scale);
sy1 = Region.clipScale(sy1, scale);
sy2 = Region.clipScale(sy2, scale);
if (SurfaceManager.getImageScale(img) != 1) { // Volatile Image
final int scale = SurfaceManager.getImageScale(img);
sx1 = Region.clipScale(sx1, scale);
sx2 = Region.clipScale(sx2, scale);
sy1 = Region.clipScale(sy1, scale);
sy2 = Region.clipScale(sy2, scale);
} else if (img instanceof MultiResolutionImage) {
// get scaled destination image size
int width = img.getWidth(observer);
int height = img.getHeight(observer);
Image resolutionVariant = getResolutionVariant(
(MultiResolutionImage) img, width, height,
dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
if (resolutionVariant != img && resolutionVariant != null) {
// recalculate source region for the resolution variant
ImageObserver rvObserver = MultiResolutionToolkitImage.
getResolutionVariantObserver(img, observer,
width, height, -1, -1);
int rvWidth = resolutionVariant.getWidth(rvObserver);
int rvHeight = resolutionVariant.getHeight(rvObserver);
if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
float widthScale = ((float) rvWidth) / width;
float heightScale = ((float) rvHeight) / height;
sx1 = Region.clipScale(sx1, widthScale);
sy1 = Region.clipScale(sy1, heightScale);
sx2 = Region.clipScale(sx2, widthScale);
sy2 = Region.clipScale(sy2, heightScale);
observer = rvObserver;
img = resolutionVariant;
}
}
}
try {
return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1,
sx2, sy2, bgcolor, observer);
......@@ -3081,6 +3138,54 @@ public final class SunGraphics2D
}
}
private Image getResolutionVariant(MultiResolutionImage img,
int srcWidth, int srcHeight, int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2) {
if (srcWidth <= 0 || srcHeight <= 0) {
return null;
}
int sw = sx2 - sx1;
int sh = sy2 - sy1;
if (sw == 0 || sh == 0) {
return null;
}
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();
} else {
destRegionWidth = dw * Math.hypot(
transform.getScaleX(), transform.getShearY());
destRegionHeight = dh * Math.hypot(
transform.getShearX(), transform.getScaleY());
}
int destImageWidth = (int) Math.abs(srcWidth * destRegionWidth / sw);
int destImageHeight = (int) Math.abs(srcHeight * destRegionHeight / sh);
Image resolutionVariant
= img.getResolutionVariant(destImageWidth, destImageHeight);
if (resolutionVariant instanceof ToolkitImage
&& ((ToolkitImage) resolutionVariant).hasError()) {
return null;
}
return resolutionVariant;
}
/**
* Draws an image scaled to x,y,w,h in nonblocking mode with a
* callback object.
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册