--- old/src/share/classes/sun/java2d/SunGraphics2D.java 2013-11-11 19:47:19.000000000 +0400 +++ new/src/share/classes/sun/java2d/SunGraphics2D.java 2013-11-11 19:47:18.000000000 +0400 @@ -93,6 +93,7 @@ import sun.misc.PerformanceLogger; import java.lang.annotation.Native; +import com.sun.awt.MultiResolutionImage; /** * This is a the master Graphics2D superclass for all of the Sun @@ -237,6 +238,7 @@ 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; @@ -283,6 +285,9 @@ if (devScale != 1) { transform.setToScale(devScale, devScale); invalidateTransform(); + resolutionVariantHint = SunHints.INTVAL_RESOLUTION_VARIANT_ON; + } else { + resolutionVariantHint = SunHints.INTVAL_RESOLUTION_VARIANT_OFF; } font = f; @@ -1249,6 +1254,10 @@ stateChanged = (strokeHint != newHint); strokeHint = newHint; break; + case SunHints.INTKEY_RESOLUTION_VARIANT: + stateChanged = (resolutionVariantHint != newHint); + resolutionVariantHint = newHint; + break; default: recognized = false; stateChanged = false; @@ -1322,6 +1331,9 @@ 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 +3062,62 @@ } // 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 { // Image scaling hints are on + // get scaled destination image size + + double scaleX = devScale; + double scaleY = devScale; + + if (transformState == TRANSFORM_TRANSLATESCALE) { + scaleX = transform.getScaleX(); + scaleY = transform.getScaleY(); + } + + int scaledImageWidth = Math.abs(Region.clipScale(dx2 - dx1, scaleX)); + int scaledImageHeight = Math.abs(Region.clipScale(dy2 - dy1, scaleY)); + + Image scaledImage = ((MultiResolutionImage) img). + getResolutionVariant(scaledImageWidth, scaledImageHeight); + + if (scaledImage != null && scaledImage != img) { + // recalculate source region for the scaled image + int width = img.getWidth(null); + int height = img.getHeight(null); + + int scaledWidth = scaledImage.getWidth(null); + int scaledHeight = scaledImage.getHeight(null); + + if (0 < width && 0 < height + && 0 < scaledWidth && 0 < scaledHeight) { + + float widthScale = (float) scaledWidth / width; + float heightScale = (float) scaledHeight / height; + + sx1 = Region.clipScale(sx1, widthScale); + sy1 = Region.clipScale(sy1, heightScale); + sx2 = Region.clipScale(sx2, widthScale); + sy2 = Region.clipScale(sy2, heightScale); + img = scaledImage; + } + } + } + try { return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);