8073320: Windows HiDPI Graphics support

Reviewed-by: flar, serb
This commit is contained in:
Alexander Scherbatiy 2015-11-13 05:02:26 -08:00
parent 7b6f3bbed8
commit a00e011325
35 changed files with 1498 additions and 181 deletions

View File

@ -37,7 +37,7 @@
<!-- Indicate JDK is high-dpi aware. -->
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
<dpiAware>true/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>

View File

@ -166,7 +166,12 @@ public abstract class CGLSurfaceData extends OGLSurfaceData {
}
@Override
public int getDefaultScale() {
public double getDefaultScaleX() {
return scale;
}
@Override
public double getDefaultScaleY() {
return scale;
}

View File

@ -1156,7 +1156,9 @@ public class LWWindowPeer
&& !(dst instanceof NullSurfaceData)
&& !(src instanceof NullSurfaceData)
&& src.getSurfaceType().equals(dst.getSurfaceType())
&& src.getDefaultScale() == dst.getDefaultScale()) {
&& src.getDefaultScaleX() == dst.getDefaultScaleX()
&& src.getDefaultScaleY() == dst.getDefaultScaleY())
{
final Rectangle size = src.getBounds();
final Blit blit = Blit.locate(src.getSurfaceType(),
CompositeType.Src,

View File

@ -50,6 +50,8 @@ public class BufImgSurfaceData extends SurfaceData {
BufferedImage bufImg;
private BufferedImageGraphicsConfig graphicsConfig;
RenderLoops solidloops;
private final double scaleX;
private final double scaleY;
private static native void initIDs(Class<?> ICM, Class<?> ICMColorData);
@ -73,6 +75,12 @@ public class BufImgSurfaceData extends SurfaceData {
}
public static SurfaceData createData(BufferedImage bufImg) {
return createData(bufImg, 1, 1);
}
public static SurfaceData createData(BufferedImage bufImg,
double scaleX, double scaleY)
{
if (bufImg == null) {
throw new NullPointerException("BufferedImage cannot be null");
}
@ -82,31 +90,36 @@ public class BufImgSurfaceData extends SurfaceData {
// REMIND: Check the image type and pick an appropriate subclass
switch (type) {
case BufferedImage.TYPE_INT_BGR:
sData = createDataIC(bufImg, SurfaceType.IntBgr);
sData = createDataIC(bufImg, SurfaceType.IntBgr, scaleX, scaleY);
break;
case BufferedImage.TYPE_INT_RGB:
sData = createDataIC(bufImg, SurfaceType.IntRgb);
sData = createDataIC(bufImg, SurfaceType.IntRgb, scaleX, scaleY);
break;
case BufferedImage.TYPE_INT_ARGB:
sData = createDataIC(bufImg, SurfaceType.IntArgb);
sData = createDataIC(bufImg, SurfaceType.IntArgb, scaleX, scaleY);
break;
case BufferedImage.TYPE_INT_ARGB_PRE:
sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
sData = createDataIC(bufImg, SurfaceType.IntArgbPre, scaleX, scaleY);
break;
case BufferedImage.TYPE_3BYTE_BGR:
sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2,
scaleX, scaleY);
break;
case BufferedImage.TYPE_4BYTE_ABGR:
sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3,
scaleX, scaleY);
break;
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3,
scaleX, scaleY);
break;
case BufferedImage.TYPE_USHORT_565_RGB:
sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null,
scaleX, scaleY);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null,
scaleX, scaleY);
break;
case BufferedImage.TYPE_BYTE_INDEXED:
{
@ -128,14 +141,16 @@ public class BufImgSurfaceData extends SurfaceData {
default:
throw new InternalError("Unrecognized transparency");
}
sData = createDataBC(bufImg, sType, 0);
sData = createDataBC(bufImg, sType, 0, scaleX, scaleY);
}
break;
case BufferedImage.TYPE_BYTE_GRAY:
sData = createDataBC(bufImg, SurfaceType.ByteGray, 0);
sData = createDataBC(bufImg, SurfaceType.ByteGray, 0,
scaleX, scaleY);
break;
case BufferedImage.TYPE_USHORT_GRAY:
sData = createDataSC(bufImg, SurfaceType.UshortGray, null);
sData = createDataSC(bufImg, SurfaceType.UshortGray, null,
scaleX, scaleY);
break;
case BufferedImage.TYPE_BYTE_BINARY:
{
@ -154,7 +169,7 @@ public class BufImgSurfaceData extends SurfaceData {
default:
throw new InternalError("Unrecognized pixel size");
}
sData = createDataBP(bufImg, sType);
sData = createDataBP(bufImg, sType, scaleX, scaleY);
}
break;
case BufferedImage.TYPE_CUSTOM:
@ -191,7 +206,7 @@ public class BufImgSurfaceData extends SurfaceData {
sType = SurfaceType.AnyDcm;
}
}
sData = createDataIC(bufImg, sType);
sData = createDataIC(bufImg, sType, scaleX, scaleY);
break;
} else if (raster instanceof ShortComponentRaster &&
raster.getNumDataElements() == 1 &&
@ -233,11 +248,12 @@ public class BufImgSurfaceData extends SurfaceData {
icm = null;
}
}
sData = createDataSC(bufImg, sType, icm);
sData = createDataSC(bufImg, sType, icm, scaleX, scaleY);
break;
}
sData = new BufImgSurfaceData(raster.getDataBuffer(),
bufImg, SurfaceType.Custom);
sData = new BufImgSurfaceData(raster.getDataBuffer(), bufImg,
SurfaceType.Custom,
scaleX, scaleY);
}
break;
}
@ -250,11 +266,15 @@ public class BufImgSurfaceData extends SurfaceData {
}
public static SurfaceData createDataIC(BufferedImage bImg,
SurfaceType sType) {
SurfaceType sType,
double scaleX,
double scaleY)
{
IntegerComponentRaster icRaster =
(IntegerComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(icRaster.getDataBuffer(), bImg, sType);
new BufImgSurfaceData(icRaster.getDataBuffer(), bImg, sType,
scaleX, scaleY);
bisd.initRaster(icRaster.getDataStorage(),
icRaster.getDataOffset(0) * 4, 0,
icRaster.getWidth(),
@ -267,11 +287,14 @@ public class BufImgSurfaceData extends SurfaceData {
public static SurfaceData createDataSC(BufferedImage bImg,
SurfaceType sType,
IndexColorModel icm) {
IndexColorModel icm,
double scaleX, double scaleY)
{
ShortComponentRaster scRaster =
(ShortComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(scRaster.getDataBuffer(), bImg, sType);
new BufImgSurfaceData(scRaster.getDataBuffer(), bImg, sType,
scaleX, scaleY);
bisd.initRaster(scRaster.getDataStorage(),
scRaster.getDataOffset(0) * 2, 0,
scRaster.getWidth(),
@ -284,11 +307,14 @@ public class BufImgSurfaceData extends SurfaceData {
public static SurfaceData createDataBC(BufferedImage bImg,
SurfaceType sType,
int primaryBank) {
int primaryBank,
double scaleX, double scaleY)
{
ByteComponentRaster bcRaster =
(ByteComponentRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType);
new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType,
scaleX, scaleY);
ColorModel cm = bImg.getColorModel();
IndexColorModel icm = ((cm instanceof IndexColorModel)
? (IndexColorModel) cm
@ -304,11 +330,14 @@ public class BufImgSurfaceData extends SurfaceData {
}
public static SurfaceData createDataBP(BufferedImage bImg,
SurfaceType sType) {
SurfaceType sType,
double scaleX, double scaleY)
{
BytePackedRaster bpRaster =
(BytePackedRaster)bImg.getRaster();
BufImgSurfaceData bisd =
new BufImgSurfaceData(bpRaster.getDataBuffer(), bImg, sType);
new BufImgSurfaceData(bpRaster.getDataBuffer(), bImg, sType,
scaleX, scaleY);
ColorModel cm = bImg.getColorModel();
IndexColorModel icm = ((cm instanceof IndexColorModel)
? (IndexColorModel) cm
@ -350,15 +379,22 @@ public class BufImgSurfaceData extends SurfaceData {
IndexColorModel icm);
public BufImgSurfaceData(DataBuffer db,
BufferedImage bufImg, SurfaceType sType)
BufferedImage bufImg,
SurfaceType sType,
double scaleX,
double scaleY)
{
super(SunWritableRaster.stealTrackable(db),
sType, bufImg.getColorModel());
this.bufImg = bufImg;
this.scaleX = scaleX;
this.scaleY = scaleY;
}
protected BufImgSurfaceData(SurfaceType surfaceType, ColorModel cm) {
super(surfaceType, cm);
this.scaleX = 1;
this.scaleY = 1;
}
public void initSolidLoops() {
@ -395,7 +431,8 @@ public class BufImgSurfaceData extends SurfaceData {
public synchronized GraphicsConfiguration getDeviceConfiguration() {
if (graphicsConfig == null) {
graphicsConfig = BufferedImageGraphicsConfig.getConfig(bufImg);
graphicsConfig = BufferedImageGraphicsConfig
.getConfig(bufImg, scaleX, scaleY);
}
return graphicsConfig;
}
@ -418,6 +455,16 @@ public class BufImgSurfaceData extends SurfaceData {
return bufImg;
}
@Override
public double getDefaultScaleX() {
return scaleX;
}
@Override
public double getDefaultScaleY() {
return scaleY;
}
public static final class ICMColorData {
private long pData = 0L;

View File

@ -45,19 +45,32 @@ public class BufferedImageGraphicsConfig
extends GraphicsConfiguration
{
private static final int numconfigs = BufferedImage.TYPE_BYTE_BINARY;
private static BufferedImageGraphicsConfig configs[] =
private static BufferedImageGraphicsConfig standardConfigs[] =
new BufferedImageGraphicsConfig[numconfigs];
private static BufferedImageGraphicsConfig scaledConfigs[] =
new BufferedImageGraphicsConfig[numconfigs];
public static BufferedImageGraphicsConfig getConfig(BufferedImage bImg) {
return getConfig(bImg, 1, 1);
}
public static BufferedImageGraphicsConfig getConfig(BufferedImage bImg,
double scaleX,
double scaleY)
{
BufferedImageGraphicsConfig ret;
int type = bImg.getType();
BufferedImageGraphicsConfig[] configs = (scaleX == 1 && scaleY == 1)
? standardConfigs : scaledConfigs;
if (type > 0 && type < numconfigs) {
ret = configs[type];
if (ret != null) {
if (ret != null && ret.scaleX == scaleX && ret.scaleY == scaleY) {
return ret;
}
}
ret = new BufferedImageGraphicsConfig(bImg, null);
ret = new BufferedImageGraphicsConfig(bImg, null, scaleX, scaleY);
if (type > 0 && type < numconfigs) {
configs[type] = ret;
}
@ -67,8 +80,16 @@ public class BufferedImageGraphicsConfig
GraphicsDevice gd;
ColorModel model;
Raster raster;
private final double scaleX;
private final double scaleY;
public BufferedImageGraphicsConfig(BufferedImage bufImg, Component comp) {
this(bufImg, comp, 1, 1);
}
public BufferedImageGraphicsConfig(BufferedImage bufImg, Component comp,
double scaleX, double scaleY)
{
if (comp == null) {
this.gd = new BufferedImageDevice(this);
} else {
@ -77,6 +98,8 @@ public class BufferedImageGraphicsConfig
}
this.model = bufImg.getColorModel();
this.raster = bufImg.getRaster().createCompatibleWritableRaster(1, 1);
this.scaleX = scaleX;
this.scaleY = scaleY;
}
/**
@ -138,7 +161,7 @@ public class BufferedImageGraphicsConfig
* For image buffers, this Transform will be the Identity transform.
*/
public AffineTransform getDefaultTransform() {
return new AffineTransform();
return AffineTransform.getScaleInstance(scaleX, scaleY);
}
/**

View File

@ -233,8 +233,17 @@ public class SunVolatileImage extends VolatileImage
* or a backup surface.
*/
public BufferedImage getBackupImage() {
return graphicsConfig.createCompatibleImage(getWidth(), getHeight(),
getTransparency());
return getBackupImage(1, 1);
}
/**
* This method creates a BufferedImage intended for use as a "snapshot"
* or a backup surface with the given horizontal and vertical scale factors.
*/
public BufferedImage getBackupImage(double scaleX, double scaleY) {
int w = (int) Math.ceil(getWidth() * scaleX);
int h = (int) Math.ceil(getHeight() * scaleY);
return graphicsConfig.createCompatibleImage(w, h, getTransparency());
}
public BufferedImage getSnapshot() {

View File

@ -290,16 +290,30 @@ public abstract class SurfaceManager {
}
/**
* Returns a scale factor of the image. This is utility method, which
* fetches information from the SurfaceData of the image.
* Returns a horizontal scale factor of the image. This is utility method,
* which fetches information from the SurfaceData of the image.
*
* @see SurfaceData#getDefaultScale
* @see SurfaceData#getDefaultScaleX
*/
public static int getImageScale(final Image img) {
public static double getImageScaleX(final Image img) {
if (!(img instanceof VolatileImage)) {
return 1;
}
final SurfaceManager sm = getManager(img);
return sm.getPrimarySurfaceData().getDefaultScale();
return sm.getPrimarySurfaceData().getDefaultScaleX();
}
/**
* Returns a vertical scale factor of the image. This is utility method,
* which fetches information from the SurfaceData of the image.
*
* @see SurfaceData#getDefaultScaleY
*/
public static double getImageScaleY(final Image img) {
if (!(img instanceof VolatileImage)) {
return 1;
}
final SurfaceManager sm = getManager(img);
return sm.getPrimarySurfaceData().getDefaultScaleY();
}
}

View File

@ -25,18 +25,16 @@
package sun.awt.image;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.ImageCapabilities;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import sun.awt.DisplayChangedListener;
import sun.awt.image.SunVolatileImage;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceData;
import sun.java2d.loops.CompositeType;
import static sun.java2d.pipe.hw.AccelSurface.*;
/**
@ -260,12 +258,16 @@ public abstract class VolatileSurfaceManager
*/
protected SurfaceData getBackupSurface() {
if (sdBackup == null) {
BufferedImage bImg = vImg.getBackupImage();
GraphicsConfiguration gc = vImg.getGraphicsConfig();
AffineTransform tx = gc.getDefaultTransform();
double scaleX = tx.getScaleX();
double scaleY = tx.getScaleY();
BufferedImage bImg = vImg.getBackupImage(scaleX, scaleY);
// Sabotage the acceleration capabilities of the BufImg surface
SunWritableRaster.stealTrackable(bImg
.getRaster()
.getDataBuffer()).setUntrackable();
sdBackup = BufImgSurfaceData.createData(bImg);
sdBackup = BufImgSurfaceData.createData(bImg, scaleX, scaleY);
}
return sdBackup;
}

View File

@ -61,7 +61,6 @@ 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;
@ -99,6 +98,7 @@ import java.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 java.awt.image.VolatileImage;
import sun.awt.image.MultiResolutionToolkitImage;
import sun.awt.image.ToolkitImage;
@ -3086,30 +3086,50 @@ public final class SunGraphics2D
}
// end of text rendering methods
private boolean isHiDPIImage(final Image img) {
return (SurfaceManager.getImageScale(img) != 1)
|| 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,
AffineTransform xform) {
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) {
if (img instanceof VolatileImage) {
final SurfaceData sd = SurfaceManager.getManager(img)
.getPrimarySurfaceData();
final double scaleX = sd.getDefaultScaleX();
final double scaleY = sd.getDefaultScaleY();
if (scaleX == 1 && scaleY == 1) {
return null;
}
sx1 = Region.clipScale(sx1, scaleX);
sx2 = Region.clipScale(sx2, scaleX);
sy1 = Region.clipScale(sy1, scaleY);
sy2 = Region.clipScale(sy2, scaleY);
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) {
AffineTransform tx = null;
if (xform != null) {
tx = new AffineTransform(transform);
transform(xform);
}
boolean result = scaleImage(img, dx1, dy1, dx2, dy2,
sx1, sy1, sx2, sy2,
bgcolor, observer);
if (tx != null) {
transform.setTransform(tx);
invalidateTransform();
}
return result;
} else if (resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_BASE
&& (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);
MultiResolutionImage mrImage = (MultiResolutionImage) img;
Image resolutionVariant = getResolutionVariant(mrImage, width, height,
dx1, dy1, dx2, dy2,
sx1, sy1, sx2, sy2,
xform);
if (resolutionVariant != img && resolutionVariant != null) {
// recalculate source region for the resolution variant
@ -3123,8 +3143,8 @@ public final class SunGraphics2D
if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
float widthScale = ((float) rvWidth) / width;
float heightScale = ((float) rvHeight) / height;
double widthScale = ((double) rvWidth) / width;
double heightScale = ((double) rvHeight) / height;
sx1 = Region.clipScale(sx1, widthScale);
sy1 = Region.clipScale(sy1, heightScale);
@ -3133,10 +3153,29 @@ public final class SunGraphics2D
observer = rvObserver;
img = resolutionVariant;
if (xform != null) {
assert dx1 == 0 && dy1 == 0;
assert dx2 == img.getWidth(observer);
assert dy2 == img.getHeight(observer);
AffineTransform renderTX = new AffineTransform(xform);
renderTX.scale(1 / widthScale, 1 / heightScale);
return transformImage(img, renderTX, observer);
}
return scaleImage(img, dx1, dy1, dx2, dy2,
sx1, sy1, sx2, sy2,
bgcolor, observer);
}
}
}
return null;
}
private boolean scaleImage(Image img, int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2,
Color bgcolor, ImageObserver observer)
{
try {
return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1,
sx2, sy2, bgcolor, observer);
@ -3156,9 +3195,30 @@ public final class SunGraphics2D
}
}
private boolean transformImage(Image img,
AffineTransform xform,
ImageObserver observer)
{
try {
return imagepipe.transformImage(this, img, xform, observer);
} catch (InvalidPipeException e) {
try {
revalidateAll();
return imagepipe.transformImage(this, img, xform, observer);
} catch (InvalidPipeException e2) {
// Still catching the exception; we are not yet ready to
// validate the surfaceData correctly. Fail for now and
// try again next time around.
return false;
}
} finally {
surfaceData.markDirty();
}
}
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) {
int sx1, int sy1, int sx2, int sy2, AffineTransform xform) {
if (srcWidth <= 0 || srcHeight <= 0) {
return null;
@ -3171,7 +3231,16 @@ public final class SunGraphics2D
return null;
}
int type = transform.getType();
AffineTransform tx;
if (xform == null) {
tx = transform;
} else {
tx = new AffineTransform(transform);
tx.concatenate(xform);
}
int type = tx.getType();
int dw = dx2 - dx1;
int dh = dy2 - dy1;
@ -3198,13 +3267,13 @@ public final class SunGraphics2D
destRegionWidth = dw;
destRegionHeight = dh;
} else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
destRegionWidth = dw * transform.getScaleX();
destRegionHeight = dh * transform.getScaleY();
destRegionWidth = dw * tx.getScaleX();
destRegionHeight = dh * tx.getScaleY();
} else {
destRegionWidth = dw * Math.hypot(
transform.getScaleX(), transform.getShearY());
tx.getScaleX(), tx.getShearY());
destRegionHeight = dh * Math.hypot(
transform.getShearX(), transform.getScaleY());
tx.getShearX(), tx.getScaleY());
}
destImageWidth = Math.abs(srcWidth * destRegionWidth / sw);
destImageHeight = Math.abs(srcHeight * destRegionHeight / sh);
@ -3277,9 +3346,11 @@ public final class SunGraphics2D
final int imgW = img.getWidth(null);
final int imgH = img.getHeight(null);
if (isHiDPIImage(img)) {
return drawHiDPIImage(img, x, y, x + width, y + height, 0, 0, imgW,
imgH, bg, observer);
Boolean hidpiImageDrawn = drawHiDPIImage(img, x, y, x + width, y + height,
0, 0, imgW, imgH, bg, observer,
null);
if (hidpiImageDrawn != null) {
return hidpiImageDrawn;
}
if (width == imgW && height == imgH) {
@ -3323,11 +3394,13 @@ public final class SunGraphics2D
return true;
}
if (isHiDPIImage(img)) {
final int imgW = img.getWidth(null);
final int imgH = img.getHeight(null);
return drawHiDPIImage(img, x, y, x + imgW, y + imgH, 0, 0, imgW,
imgH, bg, observer);
final int imgW = img.getWidth(null);
final int imgH = img.getHeight(null);
Boolean hidpiImageDrawn = drawHiDPIImage(img, x, y, x + imgW, y + imgH,
0, 0, imgW, imgH, bg, observer,
null);
if (hidpiImageDrawn != null) {
return hidpiImageDrawn;
}
try {
@ -3378,9 +3451,12 @@ public final class SunGraphics2D
return true;
}
if (isHiDPIImage(img)) {
return drawHiDPIImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
bgcolor, observer);
Boolean hidpiImageDrawn = drawHiDPIImage(img, dx1, dy1, dx2, dy2,
sx1, sy1, sx2, sy2,
bgcolor, observer, null);
if (hidpiImageDrawn != null) {
return hidpiImageDrawn;
}
if (((sx2 - sx1) == (dx2 - dx1)) &&
@ -3461,33 +3537,16 @@ public final class SunGraphics2D
return drawImage(img, 0, 0, null, observer);
}
if (isHiDPIImage(img)) {
final int w = img.getWidth(null);
final int h = img.getHeight(null);
final AffineTransform tx = new AffineTransform(transform);
transform(xform);
boolean result = drawHiDPIImage(img, 0, 0, w, h, 0, 0, w, h, null,
observer);
transform.setTransform(tx);
invalidateTransform();
return result;
final int w = img.getWidth(null);
final int h = img.getHeight(null);
Boolean hidpiImageDrawn = drawHiDPIImage(img, 0, 0, w, h, 0, 0, w, h,
null, observer, xform);
if (hidpiImageDrawn != null) {
return hidpiImageDrawn;
}
try {
return imagepipe.transformImage(this, img, xform, observer);
} catch (InvalidPipeException e) {
try {
revalidateAll();
return imagepipe.transformImage(this, img, xform, observer);
} catch (InvalidPipeException e2) {
// Still catching the exception; we are not yet ready to
// validate the surfaceData correctly. Fail for now and
// try again next time around.
return false;
}
} finally {
surfaceData.markDirty();
}
return transformImage(img, xform, observer);
}
public void drawImage(BufferedImage bImg,

View File

@ -66,6 +66,8 @@ import sun.font.FontManager;
import sun.font.FontManagerFactory;
import sun.font.FontManagerForSGE;
import sun.font.NativeFont;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;
/**
* This is an implementation of a GraphicsEnvironment object for the
@ -80,6 +82,15 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
public static boolean isOpenSolaris;
private static Font defaultFont;
private static final boolean uiScaleEnabled;
private static final double debugScale;
static {
uiScaleEnabled = "true".equals(AccessController.doPrivileged(
new GetPropertyAction("sun.java2d.uiScale.enabled", "true")));
debugScale = uiScaleEnabled ? getScaleFactor("sun.java2d.uiScale") : -1;
}
public SunGraphicsEnvironment() {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Object>() {
@ -341,4 +352,41 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
public boolean isFlipStrategyPreferred(ComponentPeer peer) {
return false;
}
public static boolean isUIScaleEnabled() {
return uiScaleEnabled;
}
public static double getDebugScale() {
return debugScale;
}
public static double getScaleFactor(String propertyName) {
String scaleFactor = AccessController.doPrivileged(
new GetPropertyAction(propertyName, "-1"));
if (scaleFactor == null || scaleFactor.equals("-1")) {
return -1;
}
try {
double units = 1.0;
if (scaleFactor.endsWith("x")) {
scaleFactor = scaleFactor.substring(0, scaleFactor.length() - 1);
} else if (scaleFactor.endsWith("dpi")) {
units = 96;
scaleFactor = scaleFactor.substring(0, scaleFactor.length() - 3);
} else if (scaleFactor.endsWith("%")) {
units = 100;
scaleFactor = scaleFactor.substring(0, scaleFactor.length() - 1);
}
double scale = Double.parseDouble(scaleFactor);
return scale <= 0 ? -1 : scale / units;
} catch (NumberFormatException ignored) {
return -1;
}
}
}

View File

@ -1059,12 +1059,22 @@ public abstract class SurfaceData
public abstract Object getDestination();
/**
* Returns default scale factor of the destination surface. Scale factor
* describes the mapping between virtual and physical coordinates of the
* Returns default horizontal scale factor of the destination surface. Scale
* factor describes the mapping between virtual and physical coordinates of the
* SurfaceData. If the scale is 2 then virtual pixel coordinates need to be
* doubled for physical pixels.
*/
public int getDefaultScale() {
public double getDefaultScaleX() {
return 1;
}
/**
* Returns default vertical scale factor of the destination surface. Scale
* factor describes the mapping between virtual and physical coordinates of the
* SurfaceData. If the scale is 2 then virtual pixel coordinates need to be
* doubled for physical pixels.
*/
public double getDefaultScaleY() {
return 1;
}
}

View File

@ -736,9 +736,10 @@ public class DrawImage implements DrawImagePipe
atfm.scale(m00, m11);
atfm.translate(srcX-sx1, srcY-sy1);
final int scale = SurfaceManager.getImageScale(img);
final int imgW = img.getWidth(null) * scale;
final int imgH = img.getHeight(null) * scale;
final double scaleX = SurfaceManager.getImageScaleX(img);
final double scaleY = SurfaceManager.getImageScaleY(img);
final int imgW = (int) Math.ceil(img.getWidth(null) * scaleX);
final int imgH = (int) Math.ceil(img.getHeight(null) * scaleY);
srcW += srcX;
srcH += srcY;
// Make sure we are not out of bounds

View File

@ -106,7 +106,7 @@ public class Win32GraphicsConfig extends GraphicsConfiguration
/**
* Return the graphics device associated with this configuration.
*/
public GraphicsDevice getDevice() {
public Win32GraphicsDevice getDevice() {
return screen;
}
@ -182,7 +182,9 @@ public class Win32GraphicsConfig extends GraphicsConfiguration
* For image buffers, this Transform will be the Identity transform.
*/
public AffineTransform getDefaultTransform() {
return new AffineTransform();
double scaleX = screen.getDefaultScaleX();
double scaleY = screen.getDefaultScaleY();
return AffineTransform.getScaleInstance(scaleX, scaleY);
}
/**

View File

@ -37,13 +37,19 @@ import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.geom.Point2D;
import java.awt.image.ColorModel;
import java.util.ArrayList;
import java.util.Vector;
import java.awt.peer.WindowPeer;
import java.security.AccessController;
import sun.awt.windows.WWindowPeer;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.opengl.WGLGraphicsConfig;
import sun.java2d.windows.WindowsFlags;
import sun.security.action.GetPropertyAction;
import static sun.awt.Win32GraphicsEnvironment.debugScaleX;
import static sun.awt.Win32GraphicsEnvironment.debugScaleY;
/**
* This is an implementation of a GraphicsDevice object for a single
@ -81,6 +87,9 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
// activation/deactivation listener for the full-screen window
private WindowListener fsWindowListener;
private float scaleX;
private float scaleY;
static {
// 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when
@ -97,6 +106,10 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
private static native void initIDs();
native void initDevice(int screen);
native void initNativeScale(int screen);
native void setNativeScale(int screen, float scaleX, float scaleY);
native float getNativeScaleX(int screen);
native float getNativeScaleY(int screen);
public Win32GraphicsDevice(int screennum) {
this.screen = screennum;
@ -109,6 +122,7 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
valid = true;
initDevice(screennum);
initScaleFactors();
}
/**
@ -128,6 +142,31 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
return screen;
}
public float getDefaultScaleX() {
return scaleX;
}
public float getDefaultScaleY() {
return scaleY;
}
private void initScaleFactors() {
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
if (debugScaleX > 0 && debugScaleY > 0) {
scaleX = debugScaleX;
scaleY = debugScaleY;
setNativeScale(screen, scaleX, scaleY);
} else {
initNativeScale(screen);
scaleX = getNativeScaleX(screen);
scaleY = getNativeScaleY(screen);
}
} else {
scaleX = 1;
scaleY = 1;
}
}
/**
* Returns whether this is a valid devicie. Device can become
* invalid as a result of device removal event.
@ -486,6 +525,7 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
configs = null;
// pass on to all top-level windows on this display
topLevels.notifyListeners();
initScaleFactors();
}
/**

View File

@ -51,6 +51,9 @@ import sun.java2d.windows.WindowsFlags;
public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment {
static final float debugScaleX;
static final float debugScaleY;
static {
// Ensure awt is loaded already. Also, this forces static init
// of WToolkit and Toolkit, which we depend upon
@ -61,6 +64,21 @@ public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment {
// Install correct surface manager factory.
SurfaceManagerFactory.setInstance(new WindowsSurfaceManagerFactory());
double sx = -1;
double sy = -1;
if (isUIScaleEnabled()) {
sx = getScaleFactor("sun.java2d.win.uiScaleX");
sy = getScaleFactor("sun.java2d.win.uiScaleY");
if (sx <= 0 || sy <= 0) {
double s = getDebugScale();
sx = s;
sy = s;
}
}
debugScaleX = (float) sx;
debugScaleY = (float) sy;
}
/**

View File

@ -294,6 +294,12 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
synchronized native void reshapeFrame(int x, int y, int width, int height);
native Dimension getNativeWindowSize();
public Dimension getScaledWindowSize() {
return getNativeWindowSize();
}
public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
if (!focusAllowedFor()) {
return false;
@ -490,8 +496,7 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
}
// get current GD
Win32GraphicsDevice oldDev = (Win32GraphicsDevice)winGraphicsConfig
.getDevice();
Win32GraphicsDevice oldDev = winGraphicsConfig.getDevice();
Win32GraphicsDevice newDev;
GraphicsDevice devs[] = GraphicsEnvironment

View File

@ -63,9 +63,12 @@ import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*;
import sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType;
import java.awt.BufferCapabilities.FlipContents;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.geom.AffineTransform;
import sun.awt.SunToolkit;
import sun.awt.image.SunVolatileImage;
import sun.awt.windows.WWindowPeer;
import sun.java2d.ScreenUpdateManager;
import sun.java2d.StateTracker;
import sun.java2d.SurfaceDataProxy;
@ -162,6 +165,8 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
private int type;
private int width, height;
private final double scaleX;
private final double scaleY;
// these fields are set from the native code when the surface is
// initialized
private int nativeWidth, nativeHeight;
@ -218,16 +223,29 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
{
super(getCustomSurfaceType(type), cm);
this.graphicsDevice = gc.getD3DDevice();
this.scaleX = type == TEXTURE ? 1 : graphicsDevice.getDefaultScaleX();
this.scaleY = type == TEXTURE ? 1 : graphicsDevice.getDefaultScaleY();
this.peer = peer;
this.type = type;
this.width = width;
this.height = height;
if (scaleX == 1 && scaleY == 1) {
this.width = width;
this.height = height;
} else if (peer instanceof WWindowPeer) {
Dimension scaledSize = ((WWindowPeer) peer).getScaledWindowSize();
this.width = scaledSize.width;
this.height = scaledSize.height;
} else {
this.width = (int) Math.ceil(width * scaleX);
this.height = (int) Math.ceil(height * scaleY);
}
this.offscreenImage = image;
this.backBuffersNum = numBackBuffers;
this.swapEffect = swapEffect;
this.syncType = vSyncType;
initOps(graphicsDevice.getScreen(), width, height);
initOps(graphicsDevice.getScreen(), this.width, this.height);
if (type == WINDOW) {
// we put the surface into the "lost"
// state; it will be restored by the D3DScreenUpdateManager
@ -240,6 +258,16 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
setBlitProxyKey(gc.getProxyKey());
}
@Override
public double getDefaultScaleX() {
return scaleX;
}
@Override
public double getDefaultScaleY() {
return scaleY;
}
@Override
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
return D3DSurfaceDataProxy.
@ -777,8 +805,12 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
public Rectangle getBounds() {
if (type == FLIP_BACKBUFFER || type == WINDOW) {
double scaleX = getDefaultScaleX();
double scaleY = getDefaultScaleY();
Rectangle r = peer.getBounds();
r.x = r.y = 0;
r.width = (int) Math.ceil(r.width * scaleX);
r.height = (int) Math.ceil(r.height * scaleY);
return r;
} else {
return new Rectangle(width, height);

View File

@ -31,8 +31,10 @@ import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import sun.awt.SunToolkit;
import sun.awt.Win32GraphicsDevice;
import sun.awt.windows.WComponentPeer;
import sun.java2d.SurfaceData;
@ -40,6 +42,8 @@ public abstract class WGLSurfaceData extends OGLSurfaceData {
protected WComponentPeer peer;
private WGLGraphicsConfig graphicsConfig;
protected double scaleX = 1;
protected double scaleY = 1;
private native void initOps(long pConfigInfo, WComponentPeer peer,
long hwnd);
@ -50,6 +54,9 @@ public abstract class WGLSurfaceData extends OGLSurfaceData {
super(gc, cm, type);
this.peer = peer;
this.graphicsConfig = gc;
Win32GraphicsDevice device = gc.getDevice();
this.scaleX = type == TEXTURE ? 1 : device.getDefaultScaleX();
this.scaleY = type == TEXTURE ? 1 : device.getDefaultScaleY();
long pConfigInfo = gc.getNativeConfigInfo();
long hwnd = peer != null ? peer.getHWnd() : 0L;
@ -57,6 +64,16 @@ public abstract class WGLSurfaceData extends OGLSurfaceData {
initOps(pConfigInfo, peer, hwnd);
}
@Override
public double getDefaultScaleX() {
return scaleX;
}
@Override
public double getDefaultScaleY() {
return scaleY;
}
public GraphicsConfiguration getDeviceConfiguration() {
return graphicsConfig;
}
@ -148,6 +165,8 @@ public abstract class WGLSurfaceData extends OGLSurfaceData {
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
r.width = (int) Math.ceil(r.width * scaleX);
r.height = (int) Math.ceil(r.height * scaleY);
return r;
}
@ -208,11 +227,11 @@ public abstract class WGLSurfaceData extends OGLSurfaceData {
{
super(peer, gc, cm, type);
this.width = width;
this.height = height;
this.width = (int) Math.ceil(width * scaleX);
this.height = (int) Math.ceil(height * scaleY);
offscreenImage = image;
initSurface(width, height);
initSurface(this.width, this.height);
}
public SurfaceData getReplacement() {
@ -222,6 +241,8 @@ public abstract class WGLSurfaceData extends OGLSurfaceData {
public Rectangle getBounds() {
if (type == FLIP_BACKBUFFER) {
Rectangle r = peer.getBounds();
r.width = (int) Math.ceil(r.width * scaleX);
r.height = (int) Math.ceil(r.height * scaleY);
r.x = r.y = 0;
return r;
} else {

View File

@ -28,6 +28,7 @@ package sun.java2d.windows;
import java.awt.Rectangle;
import java.awt.GraphicsConfiguration;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DirectColorModel;
@ -77,6 +78,9 @@ public class GDIWindowSurfaceData extends SurfaceData {
private static native void initIDs(Class<?> xorComp);
private final double scaleX;
private final double scaleY;
static {
initIDs(XORComposite.class);
if (WindowsFlags.isGdiBlitEnabled()) {
@ -265,13 +269,23 @@ public class GDIWindowSurfaceData extends SurfaceData {
this.graphicsConfig =
(Win32GraphicsConfig) peer.getGraphicsConfiguration();
this.solidloops = graphicsConfig.getSolidLoops(sType);
Win32GraphicsDevice gd =
(Win32GraphicsDevice)graphicsConfig.getDevice();
Win32GraphicsDevice gd = graphicsConfig.getDevice();
scaleX = gd.getDefaultScaleX();
scaleY = gd.getDefaultScaleY();
initOps(peer, depth, rMask, gMask, bMask, gd.getScreen());
setBlitProxyKey(graphicsConfig.getProxyKey());
}
@Override
public double getDefaultScaleX() {
return scaleX;
}
@Override
public double getDefaultScaleY() {
return scaleY;
}
/**
* {@inheritDoc}
*
@ -288,6 +302,8 @@ public class GDIWindowSurfaceData extends SurfaceData {
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
r.width = (int) Math.ceil(r.width * scaleX);
r.height = (int) Math.ceil(r.height * scaleY);
return r;
}

View File

@ -94,12 +94,21 @@ Java_sun_awt_DefaultMouseInfoPeer_fillPointWithCoords(JNIEnv *env, jclass cls, j
pointClass = (jclass)env->NewGlobalRef(pointClassLocal);
env->DeleteLocalRef(pointClassLocal);
}
int screen = AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
xID = env->GetFieldID(pointClass, "x", "I");
CHECK_NULL_RETURN(xID, (jint)0);
yID = env->GetFieldID(pointClass, "y", "I");
CHECK_NULL_RETURN(yID, (jint)0);
env->SetIntField(point, xID, pt.x);
env->SetIntField(point, yID, pt.y);
int x = (device == NULL) ? pt.x : device->ScaleDownX(pt.x);
int y = (device == NULL) ? pt.y : device->ScaleDownY(pt.y);
env->SetIntField(point, xID, x);
env->SetIntField(point, yID, y);
// Always return 0 on Windows: we assume there's always a
// virtual screen device used.

View File

@ -206,9 +206,10 @@ int AwtChoice::GetDropDownHeight()
int itemHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)0,0);
int numItemsToShow = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0,0);
numItemsToShow = min(MINIMUM_NUMBER_OF_VISIBLE_ITEMS, numItemsToShow);
// drop-down height snaps to nearest line, so add a
// fudge factor of 1/2 line to ensure last line shows
return itemHeight*numItemsToShow + itemHeight/2;
return ScaleDownY(itemHeight * numItemsToShow + itemHeight / 2);
}
// get the height of the field portion of the combobox
@ -221,7 +222,7 @@ int AwtChoice::GetFieldHeight()
// Win 4.x (3d edge) vs 3.x (1 pixel line)
borderHeight = ::GetSystemMetrics(SM_CYEDGE);
fieldHeight += borderHeight*2;
return fieldHeight;
return ScaleDownY(fieldHeight);
}
// gets the total height of the combobox, including drop down
@ -325,8 +326,8 @@ void AwtChoice::Reshape(int x, int y, int w, int h)
* Fix: Set the Choice to its actual size in the component.
*/
::GetClientRect(GetHWnd(), &rc);
env->SetIntField(target, AwtComponent::widthID, (jint)rc.right);
env->SetIntField(target, AwtComponent::heightID, (jint)rc.bottom);
env->SetIntField(target, AwtComponent::widthID, ScaleDownX(rc.right));
env->SetIntField(target, AwtComponent::heightID, ScaleDownY(rc.bottom));
env->DeleteLocalRef(target);
env->DeleteLocalRef(parent);

View File

@ -963,6 +963,12 @@ void AwtComponent::Reshape(int x, int y, int w, int h)
::MapWindowPoints(HWND_DESKTOP, ::GetParent(GetHWnd()), (LPPOINT)&rc, 2);
DTRACE_PRINTLN4("AwtComponent::Reshape from %d, %d, %d, %d", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
#endif
x = ScaleUpX(x);
y = ScaleUpY(y);
w = ScaleUpX(w);
h = ScaleUpY(h);
AwtWindow* container = GetContainer();
AwtComponent* parent = GetParent();
if (container != NULL && container == parent) {
@ -2212,8 +2218,11 @@ void AwtComponent::PaintUpdateRgn(const RECT *insets)
}
for(i = 0; i < 2; i++) {
if (un[i] != 0) {
DoCallback("handleExpose", "(IIII)V", un[i]->left, un[i]->top,
un[i]->right-un[i]->left, un[i]->bottom-un[i]->top);
DoCallback("handleExpose", "(IIII)V",
ScaleDownX(un[i]->left),
ScaleDownY(un[i]->top),
ScaleDownX(un[i]->right - un[i]->left),
ScaleDownY(un[i]->bottom - un[i]->top));
}
}
delete [] buffer;
@ -4608,6 +4617,34 @@ void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
}
}
int AwtComponent::ScaleUpX(int x) {
int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
return device == NULL ? x : device->ScaleUpX(x);
}
int AwtComponent::ScaleUpY(int y) {
int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
return device == NULL ? y : device->ScaleUpY(y);
}
int AwtComponent::ScaleDownX(int x) {
int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
return device == NULL ? x : device->ScaleDownX(x);
}
int AwtComponent::ScaleDownY(int y) {
int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice* device = devices->GetDevice(screen);
return device == NULL ? y : device->ScaleDownY(y);
}
jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
@ -4901,8 +4938,9 @@ void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
target,
id, when, modifiers,
x+insets.left, y+insets.top,
xAbs, yAbs,
ScaleDownX(x + insets.left),
ScaleDownY(y + insets.top),
ScaleDownX(xAbs), ScaleDownY(yAbs),
clickCount, popupTrigger, button);
if (safe_ExceptionOccurred(env)) {
@ -4969,8 +5007,10 @@ AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
mouseWheelEventConst,
target,
id, when, modifiers,
x+insets.left, y+insets.top,
xAbs, yAbs,
ScaleDownX(x + insets.left),
ScaleDownY(y + insets.top),
ScaleDownX(xAbs),
ScaleDownY(yAbs),
clickCount, popupTrigger,
scrollType, scrollAmount,
roundedWheelRotation, preciseWheelRotation);
@ -5476,7 +5516,8 @@ jobject AwtComponent::_GetLocationOnScreen(void *param)
RECT rect;
VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
rect.left, rect.top);
p->ScaleDownX(rect.left),
p->ScaleDownY(rect.top));
}
ret:
env->DeleteGlobalRef(self);
@ -7064,6 +7105,11 @@ void AwtComponent::VerifyState()
target = parent;
}
x = ScaleUpX(x);
y = ScaleUpY(y);
width = ScaleUpX(width);
height = ScaleUpY(height);
// Test whether component's bounds match the native window's
RECT rect;
VERIFY(::GetWindowRect(GetHWnd(), &rect));
@ -7256,5 +7302,4 @@ void ReleaseDCList(HWND hwnd, DCList &list) {
removedDCs = removedDCs->next;
delete tmpDCList;
}
}
}

View File

@ -746,6 +746,11 @@ protected:
virtual void FillBackground(HDC hMemoryDC, SIZE &size);
virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);
int ScaleUpX(int x);
int ScaleUpY(int y);
int ScaleDownX(int x);
int ScaleDownY(int y);
private:
/* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
* which are allowed to

View File

@ -398,6 +398,38 @@ static void strip_tail(wchar_t* text, wchar_t* tail) { // strips tail and any po
}
static int ScaleUpX(float x) {
int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
::GetDesktopWindow());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
return device == NULL ? x : device->ScaleUpX(x);
}
static int ScaleUpY(int y) {
int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
::GetDesktopWindow());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
return device == NULL ? y : device->ScaleUpY(y);
}
static int ScaleDownX(int x) {
int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
::GetDesktopWindow());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
return device == NULL ? x : device->ScaleDownX(x);
}
static int ScaleDownY(int y) {
int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
::GetDesktopWindow());
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
return device == NULL ? y : device->ScaleDownY(y);
}
static HFONT CreateHFont_sub(LPCWSTR name, int style, int height,
int angle=0, float awScale=1.0f)
{
@ -424,7 +456,7 @@ static HFONT CreateHFont_sub(LPCWSTR name, int style, int height,
logFont.lfUnderline = 0;//(style & java_awt_Font_UNDERLINE) != 0;
// Get point size
logFont.lfHeight = -height;
logFont.lfHeight = ScaleUpY(-height);
// Set font name
WCHAR tmpname[80];
@ -451,7 +483,7 @@ static HFONT CreateHFont_sub(LPCWSTR name, int style, int height,
VERIFY(::DeleteObject(oldFont));
}
avgWidth = tm.tmAveCharWidth;
logFont.lfWidth = (LONG)((fabs)(avgWidth*awScale));
logFont.lfWidth = (LONG) ScaleUpX((fabs) (avgWidth * awScale));
hFont = ::CreateFontIndirect(&logFont);
DASSERT(hFont != NULL);
VERIFY(::ReleaseDC(0, hDC));
@ -535,19 +567,20 @@ void AwtFont::LoadMetrics(JNIEnv *env, jobject fontMetrics)
int ascent = metrics.tmAscent;
int descent = metrics.tmDescent;
int leading = metrics.tmExternalLeading;
env->SetIntField(fontMetrics, AwtFont::ascentID, ascent);
env->SetIntField(fontMetrics, AwtFont::descentID, descent);
env->SetIntField(fontMetrics, AwtFont::leadingID, leading);
env->SetIntField(fontMetrics, AwtFont::heightID, metrics.tmAscent +
metrics.tmDescent + leading);
env->SetIntField(fontMetrics, AwtFont::maxAscentID, ascent);
env->SetIntField(fontMetrics, AwtFont::maxDescentID, descent);
env->SetIntField(fontMetrics, AwtFont::ascentID, ScaleDownY(ascent));
env->SetIntField(fontMetrics, AwtFont::descentID, ScaleDownY(descent));
env->SetIntField(fontMetrics, AwtFont::leadingID, ScaleDownX(leading));
env->SetIntField(fontMetrics, AwtFont::heightID,
ScaleDownY(metrics.tmAscent + metrics.tmDescent + leading));
env->SetIntField(fontMetrics, AwtFont::maxAscentID, ScaleDownY(ascent));
env->SetIntField(fontMetrics, AwtFont::maxDescentID, ScaleDownY(descent));
int maxHeight = ascent + descent + leading;
env->SetIntField(fontMetrics, AwtFont::maxHeightID, maxHeight);
env->SetIntField(fontMetrics, AwtFont::maxHeightID, ScaleDownY(maxHeight));
int maxAdvance = metrics.tmMaxCharWidth;
env->SetIntField(fontMetrics, AwtFont::maxAdvanceID, maxAdvance);
env->SetIntField(fontMetrics, AwtFont::maxAdvanceID, ScaleDownX(maxAdvance));
awtFont->m_overhang = metrics.tmOverhang;
@ -818,6 +851,7 @@ Java_sun_awt_windows_WFontMetrics_stringWidth(JNIEnv *env, jobject self,
jobject font = env->GetObjectField(self, AwtFont::fontID);
long ret = AwtFont::getMFStringWidth(hDC, font, str);
ret = ScaleDownX(ret);
VERIFY(::ReleaseDC(0, hDC));
return ret;
@ -924,7 +958,7 @@ Java_sun_awt_windows_WFontMetrics_bytesWidth(JNIEnv *env, jobject self,
}
env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
return result;
return ScaleDownX(result);
CATCH_BAD_ALLOC_RET(0);
}

View File

@ -80,6 +80,13 @@ void AwtRobot::MouseMove( jint x, jint y)
(PVOID)newSpeed,
SPIF_SENDCHANGE);
int primaryIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(primaryIndex);
x = (device == NULL) ? x : device->ScaleUpX(x);
y = (device == NULL) ? y : device->ScaleUpY(y);
POINT curPos;
::GetCursorPos(&curPos);
x -= curPos.x;
@ -217,11 +224,24 @@ void AwtRobot::GetRGBPixels(jint x, jint y, jint width, jint height, jintArray p
AwtWin32GraphicsDevice::SelectPalette(hdcMem, primaryIndex);
AwtWin32GraphicsDevice::RealizePalette(hdcMem, primaryIndex);
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(primaryIndex);
int sWidth = (device == NULL) ? width : device->ScaleUpX(width);
int sHeight = (device == NULL) ? height : device->ScaleUpY(height);
// copy screen image to offscreen bitmap
// CAPTUREBLT flag is required to capture WS_EX_LAYERED windows' contents
// correctly on Win2K/XP
VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y,
SRCCOPY|CAPTUREBLT) != 0);
if (width == sWidth && height == sHeight) {
VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y,
SRCCOPY | CAPTUREBLT) != 0);
} else {
int sX = (device == NULL) ? x : device->ScaleUpX(x);
int sY = (device == NULL) ? y : device->ScaleUpY(y);
VERIFY(::StretchBlt(hdcMem, 0, 0, width, height,
hdcScreen, sX, sY, sWidth, sHeight,
SRCCOPY | CAPTUREBLT) != 0);
}
static const int BITS_PER_PIXEL = 32;
static const int BYTES_PER_PIXEL = BITS_PER_PIXEL/8;

View File

@ -2355,8 +2355,13 @@ Java_sun_awt_windows_WToolkit_getScreenWidth(JNIEnv *env, jobject self)
{
TRY;
return ::GetSystemMetrics(SM_CXSCREEN);
int width = ::GetSystemMetrics(SM_CXSCREEN);
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(
AwtWin32GraphicsDevice::GetDefaultDeviceIndex());
return (device == NULL) ? width : device->ScaleDownX(width);
CATCH_BAD_ALLOC_RET(0);
}
@ -2370,7 +2375,12 @@ Java_sun_awt_windows_WToolkit_getScreenHeight(JNIEnv *env, jobject self)
{
TRY;
return ::GetSystemMetrics(SM_CYSCREEN);
int height = ::GetSystemMetrics(SM_CYSCREEN);
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(
AwtWin32GraphicsDevice::GetDefaultDeviceIndex());
return (device == NULL) ? height : device->ScaleDownY(height);
CATCH_BAD_ALLOC_RET(0);
}

View File

@ -95,19 +95,31 @@ JNIEXPORT jobject JNICALL
mid = env->GetMethodID(clazz, "<init>", "(IIII)V");
if (mid != 0) {
RECT rRW = {0, 0, 0, 0};
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) {
bounds = env->NewObject(clazz, mid,
rRW.left, rRW.top,
rRW.right - rRW.left,
rRW.bottom - rRW.top);
int x = (device == NULL) ? rRW.left : device->ScaleDownX(rRW.left);
int y = (device == NULL) ? rRW.top : device->ScaleDownY(rRW.top);
int w = (device == NULL) ? rRW.right - rRW.left
: device->ScaleDownX(rRW.right - rRW.left);
int h = (device == NULL) ? rRW.bottom - rRW.top
: device->ScaleDownY(rRW.bottom - rRW.top);
bounds = env->NewObject(clazz, mid, x, y, w, h);
}
else {
// 4910760 - don't return a null bounds, return the bounds of the
// primary screen
int w = ::GetSystemMetrics(SM_CXSCREEN);
int h = ::GetSystemMetrics(SM_CYSCREEN);
bounds = env->NewObject(clazz, mid,
0, 0,
::GetSystemMetrics(SM_CXSCREEN),
::GetSystemMetrics(SM_CYSCREEN));
device == NULL ? w : device->ScaleDownX(w),
device == NULL ? h : device->ScaleDownY(h));
}
if (safe_ExceptionOccurred(env)) {
return 0;

View File

@ -49,6 +49,12 @@
#include "dither.h"
#include "img_util_md.h"
#include "Devices.h"
#include <d2d1.h>
#pragma comment(lib, "d2d1")
#ifndef MDT_Effective_DPI
#define MDT_Effective_DPI 0
#endif
uns_ordered_dither_array img_oda_alpha;
@ -74,6 +80,8 @@ AwtWin32GraphicsDevice::AwtWin32GraphicsDevice(int screen,
{
this->screen = screen;
this->devicesArray = arr;
this->scaleX = 1;
this->scaleY = 1;
javaDevice = NULL;
colorData = new ImgColorData;
colorData->grayscale = GS_NOTGRAY;
@ -616,6 +624,104 @@ void AwtWin32GraphicsDevice::SetJavaDevice(JNIEnv *env, jobject objPtr)
javaDevice = env->NewWeakGlobalRef(objPtr);
}
/**
* Sets horizontal and vertical scale factors
*/
void AwtWin32GraphicsDevice::SetScale(float sx, float sy)
{
scaleX = sx;
scaleY = sy;
}
int AwtWin32GraphicsDevice::ScaleUpX(int x)
{
return (int)ceil(x * scaleX);
}
int AwtWin32GraphicsDevice::ScaleUpY(int y)
{
return (int)ceil(y * scaleY);
}
int AwtWin32GraphicsDevice::ScaleDownX(int x)
{
return (int)ceil(x / scaleX);
}
int AwtWin32GraphicsDevice::ScaleDownY(int y)
{
return (int)ceil(y / scaleY);
}
void AwtWin32GraphicsDevice::InitDesktopScales()
{
unsigned x = 0;
unsigned y = 0;
float dpiX = -1.0f;
float dpiY = -1.0f;
// for debug purposes
static float scale = -2.0f;
if (scale == -2) {
scale = -1;
char *uiScale = getenv("J2D_UISCALE");
if (uiScale != NULL) {
scale = (float)strtod(uiScale, NULL);
if (errno == ERANGE || scale <= 0) {
scale = -1;
}
}
}
if (scale > 0) {
SetScale(scale, scale);
return;
}
typedef HRESULT(WINAPI GetDpiForMonitorFunc)(HMONITOR, int, UINT*, UINT*);
static HMODULE hLibSHCoreDll = NULL;
static GetDpiForMonitorFunc *lpGetDpiForMonitor = NULL;
if (hLibSHCoreDll == NULL) {
hLibSHCoreDll = JDK_LoadSystemLibrary("shcore.dll");
if (hLibSHCoreDll != NULL) {
lpGetDpiForMonitor = (GetDpiForMonitorFunc*)GetProcAddress(
hLibSHCoreDll, "GetDpiForMonitor");
}
}
if (lpGetDpiForMonitor != NULL) {
HRESULT hResult = lpGetDpiForMonitor(GetMonitor(),
MDT_Effective_DPI, &x, &y);
if (hResult == S_OK) {
dpiX = static_cast<float>(x);
dpiY = static_cast<float>(y);
}
} else {
ID2D1Factory* m_pDirect2dFactory;
HRESULT res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
&m_pDirect2dFactory);
if (res == S_OK) {
m_pDirect2dFactory->GetDesktopDpi(&dpiX, &dpiY);
m_pDirect2dFactory->Release();
}
}
if (dpiX > 0 && dpiY > 0) {
SetScale(dpiX / 96, dpiY / 96);
}
}
float AwtWin32GraphicsDevice::GetScaleX()
{
return scaleX;
}
float AwtWin32GraphicsDevice::GetScaleY()
{
return scaleY;
}
/**
* Disables offscreen acceleration for this device. This
* sets a flag in the java object that is used to determine
@ -1304,3 +1410,65 @@ JNIEXPORT void JNICALL
Devices::InstanceAccess devices;
devices->GetDevice(screen)->SetJavaDevice(env, thisPtr);
}
/*
* Class: sun_awt_Win32GraphicsDevice
* Method: setNativeScale
* Signature: (I,F,F)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_setNativeScale
(JNIEnv *env, jobject thisPtr, jint screen, jfloat scaleX, jfloat scaleY)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
if (device != NULL ) {
device->SetScale(scaleX, scaleY);
}
}
/*
* Class: sun_awt_Win32GraphicsDevice
* Method: getNativeScaleX
* Signature: (I)F
*/
JNIEXPORT jfloat JNICALL
Java_sun_awt_Win32GraphicsDevice_getNativeScaleX
(JNIEnv *env, jobject thisPtr, jint screen)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
return (device == NULL) ? 1 : device->GetScaleX();
}
/*
* Class: sun_awt_Win32GraphicsDevice
* Method: getNativeScaleY
* Signature: (I)F
*/
JNIEXPORT jfloat JNICALL
Java_sun_awt_Win32GraphicsDevice_getNativeScaleY
(JNIEnv *env, jobject thisPtr, jint screen)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
return (device == NULL) ? 1 : device->GetScaleY();
}
/*
* Class: sun_awt_Win32GraphicsDevice
* Method: initNativeScale
* Signature: (I)V;
*/
JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_initNativeScale
(JNIEnv *env, jobject thisPtr, jint screen)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
if (device != NULL) {
device->InitDesktopScales();
}
}

View File

@ -66,6 +66,14 @@ public:
void Release();
void DisableOffscreenAcceleration();
void Invalidate(JNIEnv *env);
void InitDesktopScales();
void SetScale(float scaleX, float scaleY);
float GetScaleX();
float GetScaleY();
int ScaleUpX(int x);
int ScaleUpY(int y);
int ScaleDownX(int x);
int ScaleDownY(int y);
static int DeviceIndexForWindow(HWND hWnd);
static jobject GetColorModel(JNIEnv *env, jboolean dynamic,
@ -107,6 +115,8 @@ private:
LPMONITORINFO pMonitorInfo;
jobject javaDevice;
Devices *devicesArray;
float scaleX;
float scaleY;
static HDC MakeDCFromMonitor(HMONITOR);
};

View File

@ -1407,19 +1407,19 @@ BOOL AwtWindow::UpdateInsets(jobject insets)
/* Get insets into our peer directly */
jobject peerInsets = (env)->GetObjectField(peer, AwtPanel::insets_ID);
DASSERT(!safe_ExceptionOccurred(env));
if (peerInsets != NULL) { // may have been called during creation
(env)->SetIntField(peerInsets, AwtInsets::topID, m_insets.top);
(env)->SetIntField(peerInsets, AwtInsets::bottomID,
m_insets.bottom);
(env)->SetIntField(peerInsets, AwtInsets::leftID, m_insets.left);
(env)->SetIntField(peerInsets, AwtInsets::rightID, m_insets.right);
(env)->SetIntField(peerInsets, AwtInsets::topID, ScaleDownY(m_insets.top));
(env)->SetIntField(peerInsets, AwtInsets::bottomID, ScaleDownY(m_insets.bottom));
(env)->SetIntField(peerInsets, AwtInsets::leftID, ScaleDownX(m_insets.left));
(env)->SetIntField(peerInsets, AwtInsets::rightID, ScaleDownX(m_insets.right));
}
/* Get insets into the Inset object (if any) that was passed */
if (insets != NULL) {
(env)->SetIntField(insets, AwtInsets::topID, m_insets.top);
(env)->SetIntField(insets, AwtInsets::bottomID, m_insets.bottom);
(env)->SetIntField(insets, AwtInsets::leftID, m_insets.left);
(env)->SetIntField(insets, AwtInsets::rightID, m_insets.right);
(env)->SetIntField(insets, AwtInsets::topID, ScaleDownY(m_insets.top));
(env)->SetIntField(insets, AwtInsets::bottomID, ScaleDownY(m_insets.bottom));
(env)->SetIntField(insets, AwtInsets::leftID, ScaleDownX(m_insets.left));
(env)->SetIntField(insets, AwtInsets::rightID, ScaleDownX(m_insets.right));
}
env->DeleteLocalRef(peerInsets);
@ -1735,10 +1735,10 @@ MsgRouting AwtWindow::WmMove(int x, int y)
RECT rect;
::GetWindowRect(GetHWnd(), &rect);
(env)->SetIntField(target, AwtComponent::xID, rect.left);
(env)->SetIntField(target, AwtComponent::yID, rect.top);
(env)->SetIntField(peer, AwtWindow::sysXID, rect.left);
(env)->SetIntField(peer, AwtWindow::sysYID, rect.top);
(env)->SetIntField(target, AwtComponent::xID, ScaleDownX(rect.left));
(env)->SetIntField(target, AwtComponent::yID, ScaleDownY(rect.top));
(env)->SetIntField(peer, AwtWindow::sysXID, ScaleDownX(rect.left));
(env)->SetIntField(peer, AwtWindow::sysYID, ScaleDownY(rect.top));
SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_MOVED);
env->DeleteLocalRef(target);
@ -1803,12 +1803,12 @@ MsgRouting AwtWindow::WmSize(UINT type, int w, int h)
int newWidth = w + m_insets.left + m_insets.right;
int newHeight = h + m_insets.top + m_insets.bottom;
(env)->SetIntField(target, AwtComponent::widthID, newWidth);
(env)->SetIntField(target, AwtComponent::heightID, newHeight);
(env)->SetIntField(target, AwtComponent::widthID, ScaleDownX(newWidth));
(env)->SetIntField(target, AwtComponent::heightID, ScaleDownY(newHeight));
jobject peer = GetPeer(env);
(env)->SetIntField(peer, AwtWindow::sysWID, newWidth);
(env)->SetIntField(peer, AwtWindow::sysHID, newHeight);
(env)->SetIntField(peer, AwtWindow::sysWID, ScaleDownX(newWidth));
(env)->SetIntField(peer, AwtWindow::sysHID, ScaleDownY(newHeight));
if (!AwtWindow::IsResizing()) {
WindowResized();
@ -3072,6 +3072,25 @@ void AwtWindow::_SetFullScreenExclusiveModeState(void *param)
delete data;
}
void AwtWindow::_GetNativeWindowSize(void* param) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
SizeStruct *ss = (SizeStruct *)param;
jobject self = ss->window;
AwtWindow *window = NULL;
PDATA pData;
JNI_CHECK_PEER_RETURN(self);
window = (AwtWindow *)pData;
RECT rc;
::GetWindowRect(window->GetHWnd(), &rc);
ss->w = rc.right - rc.left;
ss->h = rc.bottom - rc.top;
env->DeleteGlobalRef(self);
}
extern "C" {
/*
@ -3301,6 +3320,46 @@ Java_sun_awt_windows_WWindowPeer_reshapeFrame(JNIEnv *env, jobject self,
CATCH_BAD_ALLOC;
}
/*
* Class: sun_awt_windows_WWindowPeer
* Method: getNativeWindowSize
* Signature: ()Ljava/awt/Dimension;
*/
JNIEXPORT jobject JNICALL Java_sun_awt_windows_WWindowPeer_getNativeWindowSize
(JNIEnv *env, jobject self) {
jobject res = NULL;
TRY;
SizeStruct *ss = new SizeStruct;
ss->window = env->NewGlobalRef(self);
AwtToolkit::GetInstance().SyncCall(AwtWindow::_GetNativeWindowSize, ss);
int w = ss->w;
int h = ss->h;
delete ss;
// global ref is deleted in _GetNativeWindowSize()
static jmethodID dimMID = NULL;
static jclass dimClassID = NULL;
if (dimClassID == NULL) {
jclass dimClassIDLocal = env->FindClass("java/awt/Dimension");
CHECK_NULL_RETURN(dimClassIDLocal, NULL);
dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal);
env->DeleteLocalRef(dimClassIDLocal);
}
if (dimMID == NULL) {
dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V");
CHECK_NULL_RETURN(dimMID, NULL);
}
return env->NewObject(dimClassID, dimMID, w, h);
CATCH_BAD_ALLOC_RET(NULL);
}
/*
* Class: sun_awt_windows_WWindowPeer
* Method: getSysMinWidth

View File

@ -241,6 +241,7 @@ public:
static void _UpdateWindow(void* param);
static void _RepositionSecurityWarning(void* param);
static void _SetFullScreenExclusiveModeState(void* param);
static void _GetNativeWindowSize(void* param);
inline static BOOL IsResizing() {
return sm_resizing;

View File

@ -0,0 +1,87 @@
/*
* 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.Frame;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.UIManager;
/* @test
* @bug 8073320
* @summary Windows HiDPI support
* @author Alexander Scherbatiy
* @requires (os.family == "windows")
* @run main/othervm -Dsun.java2d.win.uiScale=2 HiDPIRobotMouseClick
*/
public class HiDPIRobotMouseClick {
private static volatile int mouseX;
private static volatile int mouseY;
public static void main(String[] args) throws Exception {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception e) {
return;
}
Frame frame = new Frame();
frame.setBounds(30, 20, 400, 300);
frame.setUndecorated(true);
frame.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
mouseX = e.getXOnScreen();
mouseY = e.getYOnScreen();
}
});
frame.setVisible(true);
Robot robot = new Robot();
robot.waitForIdle();
Thread.sleep(200);
Rectangle rect = frame.getBounds();
rect.setLocation(frame.getLocationOnScreen());
int x = (int) rect.getCenterX();
int y = (int) rect.getCenterY();
robot.mouseMove(x, y);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.waitForIdle();
if (x != mouseX || y != mouseY) {
throw new RuntimeException("Wrong mouse click point!");
}
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import javax.swing.UIManager;
/* @test
* @bug 8073320
* @summary Windows HiDPI support
* @author Alexander Scherbatiy
* @requires (os.family == "windows")
* @run main/othervm -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2
* HiDPIRobotScreenCaptureTest
*/
public class HiDPIRobotScreenCaptureTest {
private static final Color[] COLORS = {
Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED};
public static void main(String[] args) throws Exception {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception e) {
return;
}
Frame frame = new Frame();
frame.setBounds(40, 30, 400, 300);
frame.setUndecorated(true);
Panel panel = new Panel(new BorderLayout());
Canvas canvas = new Canvas() {
@Override
public void paint(Graphics g) {
super.paint(g);
int w = getWidth();
int h = getHeight();
g.setColor(COLORS[0]);
g.fillRect(0, 0, w / 2, h / 2);
g.setColor(COLORS[1]);
g.fillRect(w / 2, 0, w / 2, h / 2);
g.setColor(COLORS[2]);
g.fillRect(0, h / 2, w / 2, h / 2);
g.setColor(COLORS[3]);
g.fillRect(w / 2, h / 2, w / 2, h / 2);
}
};
panel.add(canvas);
frame.add(panel);
frame.setVisible(true);
Robot robot = new Robot();
robot.waitForIdle();
Thread.sleep(200);
Rectangle rect = canvas.getBounds();
rect.setLocation(canvas.getLocationOnScreen());
BufferedImage image = robot.createScreenCapture(rect);
frame.dispose();
int w = image.getWidth();
int h = image.getHeight();
if (w != frame.getWidth() || h != frame.getHeight()) {
throw new RuntimeException("Wrong image size!");
}
if (image.getRGB(w / 4, h / 4) != COLORS[0].getRGB()) {
throw new RuntimeException("Wrong image color!");
}
if (image.getRGB(3 * w / 4, h / 4) != COLORS[1].getRGB()) {
throw new RuntimeException("Wrong image color!");
}
if (image.getRGB(w / 4, 3 * h / 4) != COLORS[2].getRGB()) {
throw new RuntimeException("Wrong image color!");
}
if (image.getRGB(3 * w / 4, 3 * h / 4) != COLORS[3].getRGB()) {
throw new RuntimeException("Wrong image color!");
}
}
}

View File

@ -0,0 +1,139 @@
/*
* 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.Dialog;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.UIManager;
/* @test
* @bug 8073320
* @summary Windows HiDPI support
* @author Alexander Scherbatiy
* @requires (os.family == "windows")
* @run main/othervm -Dsun.java2d.uiScale.enabled=false
* -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2
* HiDPIPropertiesWindowsTest UISCALE_DISABLED
* @run main/othervm -Dsun.java2d.uiScale.enabled=false
* -Dsun.java2d.uiScale=3
* HiDPIPropertiesWindowsTest UISCALE_DISABLED
* @run main/othervm -Dsun.java2d.uiScale.enabled=false
* -Dsun.java2d.uiScale=3
* -Dsun.java2d.win.uiScaleX=5 -Dsun.java2d.win.uiScaleY=6
* HiDPIPropertiesWindowsTest UISCALE_DISABLED
* @run main/othervm -Dsun.java2d.uiScale.enabled=true
* -Dsun.java2d.uiScale=3
* HiDPIPropertiesWindowsTest UISCALE_3
* @run main/othervm -Dsun.java2d.uiScale.enabled=true
* -Dsun.java2d.uiScale=4
* -Dsun.java2d.win.uiScaleX=2 -Dsun.java2d.win.uiScaleY=3
* HiDPIPropertiesWindowsTest UISCALE_2X3
* @run main/othervm -Dsun.java2d.uiScale.enabled=true
* -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2
* HiDPIPropertiesWindowsTest UISCALE_3X2
* @run main/othervm -Dsun.java2d.uiScale=4
* HiDPIPropertiesWindowsTest UISCALE_4
* @run main/othervm -Dsun.java2d.uiScale=4
* -Dsun.java2d.win.uiScaleX=2 -Dsun.java2d.win.uiScaleY=3
* HiDPIPropertiesWindowsTest UISCALE_2X3
* @run main/othervm -Dsun.java2d.win.uiScaleX=4 -Dsun.java2d.win.uiScaleY=5
* HiDPIPropertiesWindowsTest UISCALE_4X5
* @run main/othervm -Dsun.java2d.uiScale=3
* -Dsun.java2d.win.uiScaleX=0 -Dsun.java2d.win.uiScaleY=0
* HiDPIPropertiesWindowsTest UISCALE_3
* @run main/othervm -Dsun.java2d.uiScale=4
* -Dsun.java2d.win.uiScaleX=-7 -Dsun.java2d.win.uiScaleY=-8
* HiDPIPropertiesWindowsTest UISCALE_4
* @run main/othervm -Dsun.java2d.uiScale=4x
* HiDPIPropertiesWindowsTest UISCALE_4
* @run main/othervm -Dsun.java2d.win.uiScaleX=4x -Dsun.java2d.win.uiScaleY=5x
* HiDPIPropertiesWindowsTest UISCALE_4X5
* @run main/othervm -Dsun.java2d.uiScale=384dpi
* HiDPIPropertiesWindowsTest UISCALE_4
* @run main/othervm -Dsun.java2d.uiScale=300%
* HiDPIPropertiesWindowsTest UISCALE_3
* @run main/othervm -Dsun.java2d.win.uiScaleX=400% -Dsun.java2d.win.uiScaleY=500%
* HiDPIPropertiesWindowsTest UISCALE_4X5
* @run main/othervm -Dsun.java2d.win.uiScaleX=288dpi -Dsun.java2d.win.uiScaleY=192dpi
* HiDPIPropertiesWindowsTest UISCALE_3X2
* @run main/othervm -Dsun.java2d.win.uiScaleX=200% -Dsun.java2d.win.uiScaleY=288dpi
* HiDPIPropertiesWindowsTest UISCALE_2X3
*/
public class HiDPIPropertiesWindowsTest {
public static void main(String[] args) throws Exception {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception e) {
return;
}
String testCase = args[0];
switch (testCase) {
case "UISCALE_DISABLED":
testScale(1.0, 1.0);
break;
case "UISCALE_3":
testScale(3.0, 3.0);
break;
case "UISCALE_4":
testScale(4.0, 4.0);
break;
case "UISCALE_2X3":
testScale(2.0, 3.0);
break;
case "UISCALE_3X2":
testScale(3.0, 2.0);
break;
case "UISCALE_4X5":
testScale(4.0, 5.0);
break;
default:
throw new RuntimeException("Unknown test case: " + testCase);
}
}
private static void testScale(double scaleX, double scaleY) {
Dialog dialog = new Dialog((Frame) null, true) {
@Override
public void paint(Graphics g) {
super.paint(g);
AffineTransform tx = ((Graphics2D) g).getTransform();
dispose();
if (scaleX != tx.getScaleX() || scaleY != tx.getScaleY()) {
throw new RuntimeException(String.format("Wrong scale:"
+ "[%f, %f] instead of [%f, %f].",
tx.getScaleX(), tx.getScaleY(), scaleX, scaleY));
}
}
};
dialog.setSize(200, 300);
dialog.setVisible(true);
}
}

View File

@ -0,0 +1,248 @@
/*
* 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.Frame;
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_SIZE_FIT;
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 8073320
* @author Alexander Scherbatiy
* @summary Windows HiDPI support
* @modules java.desktop/sun.java2d java.desktop/sun.java2d.loops
* @run main MultiResolutionDrawImageWithTransformTest
*/
public class MultiResolutionDrawImageWithTransformTest {
private static final int SCREEN_SIZE = 400;
private static final int IMAGE_SIZE = SCREEN_SIZE / 4;
private static final Color BACKGROUND_COLOR = Color.PINK;
private static final Color[] COLORS = {
Color.CYAN, Color.GREEN, Color.BLUE, Color.ORANGE
};
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);
// scale 1, transform 1, resolution variant 1
Color color = getImageColor(mrImage, 1, 1);
if (!getColorForScale(1).equals(color)) {
throw new RuntimeException("Wrong resolution variant!");
}
// scale 1, transform 2, resolution variant 2
color = getImageColor(mrImage, 1, 2);
if (!getColorForScale(2).equals(color)) {
throw new RuntimeException("Wrong resolution variant!");
}
// scale 2, transform 1, resolution variant 2
color = getImageColor(mrImage, 2, 1);
if (!getColorForScale(2).equals(color)) {
throw new RuntimeException("Wrong resolution variant!");
}
// scale 2, transform 2, resolution variant 4
color = getImageColor(mrImage, 2, 2);
if (!getColorForScale(4).equals(color)) {
throw new RuntimeException("Wrong resolution variant!");
}
}
private static Color getColorForScale(int scale) {
return COLORS[scale - 1];
}
private static Color getImageColor(Image image, double configScale,
double transformScale) {
TestSurfaceData surface = new TestSurfaceData(SCREEN_SIZE, SCREEN_SIZE,
configScale);
SunGraphics2D g2d = new SunGraphics2D(surface,
Color.BLACK, Color.BLACK, null);
g2d.setRenderingHint(KEY_RESOLUTION_VARIANT,
VALUE_RESOLUTION_VARIANT_SIZE_FIT);
AffineTransform tx = AffineTransform.getScaleInstance(transformScale,
transformScale);
g2d.drawImage(image, tx, null);
g2d.dispose();
int backgroundX = (int) (1.5 * image.getWidth(null) * transformScale);
int backgroundY = (int) (1.5 * image.getHeight(null) * transformScale);
Color backgroundColor = surface.getColor(backgroundX, backgroundY);
//surface.show(String.format("Config: %f, transform: %f", configScale, transformScale));
if (!BACKGROUND_COLOR.equals(backgroundColor)) {
throw new RuntimeException("Wrong background color!");
}
return surface.getColor(IMAGE_SIZE / 4, IMAGE_SIZE / 4);
}
private static int getSize(int i) {
return (i + 1) * IMAGE_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);
g.fillRect(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);
Graphics imageGraphics = buffImage.createGraphics();
imageGraphics.setColor(BACKGROUND_COLOR);
imageGraphics.fillRect(0, 0, this.width, this.height);
imageGraphics.dispose();
}
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.");
}
private void show(String title) {
Frame frame = new Frame() {
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(buffImage, 0, 0, this);
g.setColor(Color.GRAY);
g.drawRect(0, 0, width, height);
g.drawRect(0, height / 2, width, height / 2);
g.drawRect(width / 2, 0, width / 2, height);
}
};
frame.setTitle(title);
frame.setSize(width, height);
frame.setVisible(true);
}
}
}