--- old/src/java.desktop/share/classes/java/awt/Robot.java 2017-02-08 13:46:52.049859000 +0530
+++ new/src/java.desktop/share/classes/java/awt/Robot.java 2017-02-08 13:46:51.813859000 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -27,6 +27,9 @@
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BaseMultiResolutionImage;
+import java.awt.image.MultiResolutionImage;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
@@ -390,6 +393,11 @@
* @return Color of the pixel
*/
public synchronized Color getPixelColor(int x, int y) {
+ AffineTransform tx = GraphicsEnvironment.
+ getLocalGraphicsEnvironment().getDefaultScreenDevice().
+ getDefaultConfiguration().getDefaultTransform();
+ x = (int) (x * tx.getScaleX());
+ y = (int) (y * tx.getScaleY());
Color color = new Color(peer.getRGBPixel(x, y));
return color;
}
@@ -405,13 +413,56 @@
* @see AWTPermission
*/
public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
+ return createCompatibleImage(screenRect, false)[0];
+ }
+
+ /**
+ * Creates an image containing pixels read from the screen.
+ * This image does not include the mouse cursor.
+ * This method should be used in case where there is a scaling transform
+ * from user space to screen (device) space.
+ * Typically this means that the display is a high resolution screen,
+ * although strictly it means any case in which there is such a transform.
+ * Returns a {@link java.awt.image.MultiResolutionImage}.
+ *
+ * For a non-scaled display, the {@code MultiResolutionImage}
+ * will have one image variant:
+ *
+ * - Base Image with user specified size.
+ *
+ *
+ * For a high resolution display where there is scaling transform,
+ * the {@code MultiResolutionImage} will have two image variants:
+ *
+ * - Base Image with user specified size. This is scaled from the screen.
+ *
- Native device resolution image with device size pixels.
+ *
+ * @param screenRect Rect to capture in screen coordinates
+ * @return The captured image
+ * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero
+ * @throws SecurityException if {@code readDisplayPixels} permission is not granted
+ * @see SecurityManager#checkPermission
+ * @see AWTPermission
+ */
+ public synchronized MultiResolutionImage
+ createMultiResolutionScreenCapture(Rectangle screenRect) {
+
+ return new BaseMultiResolutionImage(
+ createCompatibleImage(screenRect, true));
+ }
+
+ private synchronized BufferedImage[]
+ createCompatibleImage(Rectangle screenRect, boolean isHiDPI) {
+
checkScreenCaptureAllowed();
checkValidRect(screenRect);
- BufferedImage image;
+ BufferedImage lowResolutionImage;
+ BufferedImage highResolutionImage;
DataBufferInt buffer;
WritableRaster raster;
+ BufferedImage[] imageArray;
if (screenCapCM == null) {
/*
@@ -421,31 +472,92 @@
*/
screenCapCM = new DirectColorModel(24,
- /* red mask */ 0x00FF0000,
- /* green mask */ 0x0000FF00,
- /* blue mask */ 0x000000FF);
+ /* red mask */ 0x00FF0000,
+ /* green mask */ 0x0000FF00,
+ /* blue mask */ 0x000000FF);
}
+ int[] bandmasks = new int[3];
+ bandmasks[0] = screenCapCM.getRedMask();
+ bandmasks[1] = screenCapCM.getGreenMask();
+ bandmasks[2] = screenCapCM.getBlueMask();
+
// need to sync the toolkit prior to grabbing the pixels since in some
// cases rendering to the screen may be delayed
Toolkit.getDefaultToolkit().sync();
-
+ AffineTransform tx = GraphicsEnvironment.
+ getLocalGraphicsEnvironment().getDefaultScreenDevice().
+ getDefaultConfiguration().getDefaultTransform();
+ double uiScaleX = tx.getScaleX();
+ double uiScaleY = tx.getScaleY();
int pixels[];
- int[] bandmasks = new int[3];
- pixels = peer.getRGBPixels(screenRect);
- buffer = new DataBufferInt(pixels, pixels.length);
+ if (uiScaleX == 1 && uiScaleY == 1) {
- bandmasks[0] = screenCapCM.getRedMask();
- bandmasks[1] = screenCapCM.getGreenMask();
- bandmasks[2] = screenCapCM.getBlueMask();
+ pixels = peer.getRGBPixels(screenRect);
+ buffer = new DataBufferInt(pixels, pixels.length);
- raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);
- SunWritableRaster.makeTrackable(buffer);
+ bandmasks[0] = screenCapCM.getRedMask();
+ bandmasks[1] = screenCapCM.getGreenMask();
+ bandmasks[2] = screenCapCM.getBlueMask();
+
+ raster = Raster.createPackedRaster(buffer, screenRect.width,
+ screenRect.height, screenRect.width, bandmasks, null);
+ SunWritableRaster.makeTrackable(buffer);
+
+ highResolutionImage = new BufferedImage(screenCapCM, raster,
+ false, null);
+ imageArray = new BufferedImage[1];
+ imageArray[0] = highResolutionImage;
+
+ } else {
+
+ int sX = (int) Math.floor(screenRect.x * uiScaleX);
+ int sY = (int) Math.floor(screenRect.y * uiScaleY);
+ int sWidth = (int) Math.ceil(screenRect.width * uiScaleX);
+ int sHeight = (int) Math.ceil(screenRect.height * uiScaleY);
+ int temppixels[];
+ Rectangle scaledRect = new Rectangle(sX, sY, sWidth, sHeight);
+ temppixels = peer.getRGBPixels(scaledRect);
+
+ // HighResolutionImage
+ pixels = temppixels;
+ buffer = new DataBufferInt(pixels, pixels.length);
+ raster = Raster.createPackedRaster(buffer, scaledRect.width,
+ scaledRect.height, scaledRect.width, bandmasks, null);
+ SunWritableRaster.makeTrackable(buffer);
+
+ highResolutionImage = new BufferedImage(screenCapCM, raster,
+ false, null);
+
+
+ // LowResolutionImage
+ lowResolutionImage = new BufferedImage(screenRect.width,
+ screenRect.height, highResolutionImage.getType());
+ Graphics2D g = lowResolutionImage.createGraphics();
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g.drawImage(highResolutionImage, 0, 0,
+ screenRect.width, screenRect.height,
+ 0, 0, scaledRect.width, scaledRect.height, null);
+ g.dispose();
+
+ if(!isHiDPI) {
+ imageArray = new BufferedImage[1];
+ imageArray[0] = lowResolutionImage;
+ } else {
+ imageArray = new BufferedImage[2];
+ imageArray[0] = lowResolutionImage;
+ imageArray[1] = highResolutionImage;
+ }
- image = new BufferedImage(screenCapCM, raster, false, null);
+ }
- return image;
+ return imageArray;
}
private static void checkValidRect(Rectangle rect) {
--- old/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp 2017-02-08 13:46:52.605859000 +0530
+++ new/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp 2017-02-08 13:46:52.397859000 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -224,24 +224,11 @@
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
- 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);
- }
+ VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y,
+ SRCCOPY | CAPTUREBLT) != 0);
static const int BITS_PER_PIXEL = 32;
static const int BYTES_PER_PIXEL = BITS_PER_PIXEL/8;
--- old/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java 2017-02-08 13:46:53.169859000 +0530
+++ new/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java 2017-02-08 13:46:52.957859000 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -115,8 +115,7 @@
@Override
public int getRGBPixel(int x, int y) {
int pixelArray[] = new int[1];
- getRGBPixelsImpl(xgc, x, y, 1, 1, xgc.getScale(), pixelArray,
- useGtk);
+ getRGBPixelsImpl(xgc, x, y, 1, 1, pixelArray, useGtk);
return pixelArray[0];
}
@@ -124,7 +123,7 @@
public int [] getRGBPixels(Rectangle bounds) {
int pixelArray[] = new int[bounds.width*bounds.height];
getRGBPixelsImpl(xgc, bounds.x, bounds.y, bounds.width, bounds.height,
- xgc.getScale(), pixelArray, useGtk);
+ pixelArray, useGtk);
return pixelArray;
}
@@ -140,6 +139,5 @@
private static synchronized native void keyReleaseImpl(int keycode);
private static synchronized native void getRGBPixelsImpl(X11GraphicsConfig xgc,
- int x, int y, int width, int height, int scale,
- int pixelArray[], boolean isGtkSupported);
+ int x, int y, int width, int height, int pixelArray[], boolean isGtkSupported);
}
--- old/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c 2017-02-08 13:46:53.689859000 +0530
+++ new/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c 2017-02-08 13:46:53.517859000 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -276,7 +276,6 @@
jint jy,
jint jwidth,
jint jheight,
- jint scale,
jintArray pixelArray,
jboolean useGtk) {
XImage *image;
@@ -298,11 +297,6 @@
AWT_LOCK();
- jint sx = jx * scale;
- jint sy = jy * scale;
- jint swidth = jwidth * scale;
- jint sheight = jheight * scale;
-
rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
if (!useGtk) {
@@ -314,10 +308,10 @@
}
if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
- || sx + swidth <= attr.x
- || attr.x + attr.width <= sx
- || sy + sheight <= attr.y
- || attr.y + attr.height <= sy) {
+ || jx + jwidth <= attr.x
+ || attr.x + attr.width <= jx
+ || jy + jheight <= attr.y
+ || attr.y + attr.height <= jy) {
AWT_UNLOCK();
return; // Does not intersect with root window
@@ -326,26 +320,25 @@
gboolean gtk_failed = TRUE;
jint _x, _y;
- jint x = MAX(sx, attr.x);
- jint y = MAX(sy, attr.y);
- jint width = MIN(sx + swidth, attr.x + attr.width) - x;
- jint height = MIN(sy + sheight, attr.y + attr.height) - y;
-
+ jint x = MAX(jx, attr.x);
+ jint y = MAX(jy, attr.y);
+ jint width = MIN(jx + jwidth, attr.x + attr.width) - x;
+ jint height = MIN(jy + jheight, attr.y + attr.height) - y;
- int dx = attr.x > sx ? attr.x - sx : 0;
- int dy = attr.y > sy ? attr.y - sy : 0;
+ int dx = attr.x > jx ? attr.x - jx : 0;
+ int dy = attr.y > jy ? attr.y - jy : 0;
int index;
if (useGtk) {
gtk->gdk_threads_enter();
gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width,
- height, jwidth, dx, dy, scale);
+ height, jwidth, dx, dy, 1);
gtk->gdk_threads_leave();
}
if (gtk_failed) {
- image = getWindowImage(awt_display, rootWindow, sx, sy, swidth, sheight);
+ image = getWindowImage(awt_display, rootWindow, x, y, width, height);
ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
@@ -355,15 +348,10 @@
return;
}
- dx /= scale;
- dy /= scale;
- width /= scale;
- height /= scale;
-
/* convert to Java ARGB pixels */
for (_y = 0; _y < height; _y++) {
for (_x = 0; _x < width; _x++) {
- jint pixel = (jint) XGetPixel(image, _x * scale, _y * scale);
+ jint pixel = (jint) XGetPixel(image, _x, _y);
/* Note ignore upper
* 32-bits on 64-bit
* OSes.
--- old/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m 2017-02-08 13:46:54.229859000 +0530
+++ new/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m 2017-02-08 13:46:54.053859000 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -276,7 +276,7 @@
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CRobot_nativeGetScreenPixels
(JNIEnv *env, jobject peer,
- jint x, jint y, jint width, jint height, jintArray pixels)
+ jint x, jint y, jint width, jint height, jdouble scale, jintArray pixels)
{
JNF_COCOA_ENTER(env);
@@ -285,10 +285,11 @@
jint picWidth = width;
jint picHeight = height;
- CGRect screenRect = CGRectMake(picX, picY, picWidth, picHeight);
+ CGRect screenRect = CGRectMake(picX / scale, picY / scale,
+ picWidth / scale, picHeight / scale);
CGImageRef screenPixelsImage = CGWindowListCreateImage(screenRect,
kCGWindowListOptionOnScreenOnly,
- kCGNullWindowID, kCGWindowImageDefault);
+ kCGNullWindowID, kCGWindowImageBestResolution);
if (screenPixelsImage == NULL) {
return;
--- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java 2017-02-08 13:46:54.693859000 +0530
+++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java 2017-02-08 13:46:54.537859000 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -174,7 +174,8 @@
@Override
public int getRGBPixel(int x, int y) {
int c[] = new int[1];
- getScreenPixels(new Rectangle(x, y, 1, 1), c);
+ double scale = fDevice.getScaleFactor();
+ getScreenPixels(new Rectangle(x, y, (int) scale, (int) scale), c);
return c[0];
}
@@ -185,7 +186,7 @@
*/
@Override
public int [] getRGBPixels(final Rectangle bounds) {
- int c[] = new int[bounds.width * bounds.height];
+ int c[] = new int[bounds.width * bounds.height];
getScreenPixels(bounds, c);
return c;
@@ -198,7 +199,8 @@
boolean isMouseMove);
private native void keyEvent(int javaKeyCode, boolean keydown);
private void getScreenPixels(Rectangle r, int[] pixels){
- nativeGetScreenPixels(r.x, r.y, r.width, r.height, pixels);
+ double scale = fDevice.getScaleFactor();
+ nativeGetScreenPixels(r.x, r.y, r.width, r.height, scale, pixels);
}
- private native void nativeGetScreenPixels(int x, int y, int width, int height, int[] pixels);
+ private native void nativeGetScreenPixels(int x, int y, int width, int height, double scale, int[] pixels);
}
--- /dev/null 2017-02-08 10:49:16.884329000 +0530
+++ new/test/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java 2017-02-08 13:46:55.021859000 +0530
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+ /*
+ * @test
+ * @bug 8162959
+ * @summary Validate output of createMultiResolutionScreenCapture
+ * new API which returns MultiResolutionImage.
+ * @run main/othervm -Dsun.java2d.uiScale=1 ScreenCaptureTest
+ * @run main/othervm -Dsun.java2d.uiScale=2 ScreenCaptureTest
+ */
+import java.awt.Dimension;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.MultiResolutionImage;
+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.Robot;
+import java.util.List;
+
+public class ScreenCaptureTest {
+
+ private static Robot robot;
+ private static Frame frame;
+ private static boolean isHiDPI = true;
+ private static final Color[] COLORS = {
+ Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED};
+
+ public static void main(String[] args) throws Exception {
+
+ frame = new Frame();
+ frame.setBounds(0, 0, 400, 400);
+ frame.setUndecorated(true);
+ robot = new Robot();
+ Panel panel = new Panel(new BorderLayout());
+ Canvas canvas = new Canvas() {
+ 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.delay(500);
+ robot.waitForIdle();
+
+ int w = frame.getWidth();
+ int h = frame.getHeight();
+
+ // getPixelColor Test
+ // Check pixel color in first quardant GREEN; x=100, y=100
+ if (!robot.getPixelColor(w / 4, h / 4).equals(COLORS[0])) {
+ throw new RuntimeException("Wrong Pixel Color! Expected GREEN");
+ }
+ // Check pixel color in second quardant; BLUE, x=300, y=100
+ if (!robot.getPixelColor(3 * w / 4, h / 4).equals(COLORS[1])) {
+ throw new RuntimeException("Wrong Pixel Color! Expected BLUE");
+ }
+ // Check pixel color in third quardant; ORANGE, x=100, y=300
+ if (!robot.getPixelColor(w / 4, 3 * h / 4).equals(COLORS[2])) {
+ throw new RuntimeException("Wrong Pixel Color! Expected ORANGE");
+ }
+ // Check pixel color in fourth quardant; RED, x=300, y=300
+ if (!robot.getPixelColor(3 * w / 4, 3 * h / 4).equals(COLORS[3])) {
+ throw new RuntimeException("Wrong Pixel Color! Expected RED");
+ }
+
+ // createScreenCaptureTest
+ AffineTransform tx = GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration()
+ .getDefaultTransform();
+
+ if (tx.getScaleX() == 1 && tx.getScaleY() == 1) {
+ isHiDPI = false;
+ }
+
+ MultiResolutionImage image
+ = robot.createMultiResolutionScreenCapture(frame.getBounds());
+ List imageList = image.getResolutionVariants();
+ int size = imageList.size();
+ BufferedImage lowResImage;
+ BufferedImage highResImage;
+
+ if (!isHiDPI) {
+ // Check if output is MultiResolutionImage with one variant
+ if (size != 1) {
+ throw new RuntimeException(" Invalid variant size");
+ }
+
+ lowResImage = (BufferedImage) imageList.get(0);
+ System.out.println(frame.getBounds());
+ System.out.println(lowResImage.getWidth()+" "+lowResImage.getHeight());
+ if (frame.getWidth() != lowResImage.getWidth()
+ || frame.getHeight() != lowResImage.getHeight()) {
+ throw new RuntimeException(" Invalid Image size");
+ }
+
+ } else {
+ // Check if output contains two variants.
+ if (size != 2) {
+ throw new RuntimeException(" Invalid variant size");
+ }
+
+ // Check if hight resolution image size is scale times low resolution image.
+ lowResImage = (BufferedImage) imageList.get(0);
+ highResImage = (BufferedImage) imageList.get(1);
+
+ int lW = (int) lowResImage.getWidth();
+ int lH = (int) lowResImage.getHeight();
+ int hW = (int) highResImage.getWidth();
+ int hH = (int) highResImage.getHeight();
+
+ if ( hW != (tx.getScaleX() * lW) || hH != (tx.getScaleY() * lH)) {
+ throw new RuntimeException(" Invalid Resolution Variants");
+ }
+
+ // Check if both image colors are same at some location.
+ if (lowResImage.getRGB(lW / 4, lH / 4)
+ != highResImage.getRGB(hW / 4, hH / 4)) {
+ throw new RuntimeException("Wrong image color!");
+ }
+
+ if (lowResImage.getRGB(3 * lW / 4, lH / 4)
+ != highResImage.getRGB(3 * hW / 4, hH / 4)) {
+ throw new RuntimeException("Wrong image color!");
+ }
+
+ if (lowResImage.getRGB(lW / 4, 3 * lH / 4)
+ != highResImage.getRGB(hW / 4, 3 * hH / 4)) {
+ throw new RuntimeException("Wrong image color!");
+ }
+
+ if (lowResImage.getRGB(3 * lW / 4, 3 * lH / 4)
+ != highResImage.getRGB(3 * hW / 4, 3 * hH / 4)) {
+ throw new RuntimeException("Wrong image color!");
+ }
+
+ }
+
+ frame.dispose();
+ }
+
+}
--- /dev/null 2017-02-08 10:49:16.884329000 +0530
+++ new/test/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureResolutionTest.java 2017-02-08 13:46:55.505859000 +0530
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+ /*
+ * @test
+ * @bug 8162959
+ * @summary Visually validate multiresolution screencapture.
+ * @run main/othervm/manual -Dsun.java2d.uiScale=2 ScreenCaptureResolutionTest
+ */
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.concurrent.CountDownLatch;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.concurrent.TimeUnit;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import java.awt.Robot;
+import java.awt.image.BufferedImage;
+import java.util.List;
+import java.awt.Image;
+import java.awt.image.MultiResolutionImage;
+
+public class ScreenCaptureResolutionTest {
+
+ public static void main(String args[]) throws Exception {
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ TestUI test = new TestUI(latch);
+
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ test.createUI();
+ } catch (Exception ex) {
+ throw new RuntimeException("Exception while creating UI");
+ }
+ }
+ });
+ latch.await(3, TimeUnit.SECONDS);
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ test.validateScreenCapture();
+ } catch (Exception ex) {
+ throw new RuntimeException("Exception while"
+ + " validating ScreenCapture");
+ }
+ }
+ });
+ boolean status = latch.await(5, TimeUnit.MINUTES);
+ if (!status) {
+ System.out.println("Test timed out.");
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ test.disposeUI();
+ } catch (Exception ex) {
+ throw new RuntimeException("Exception while disposing UI");
+ }
+ }
+ });
+
+ if (test.testResult == false) {
+ throw new RuntimeException("Test Failed.");
+ }
+ }
+}
+
+class TestUI {
+
+ private static JFrame mainFrame;
+ private static JFrame outputImageFrame;
+ private static JFrame inputImageFrame;
+ private static JPanel outputControlPanel;
+ private static JPanel mainControlPanel;
+
+ private static JTextArea instructionTextArea;
+
+ private static JPanel inputImagePanel;
+ private static JPanel resultButtonPanel;
+ private static JButton passButton;
+ private static JButton failButton;
+
+ private static GridBagLayout layout;
+ private final CountDownLatch latch;
+ public boolean testResult = false;
+
+ public TestUI(CountDownLatch latch) throws Exception {
+ this.latch = latch;
+ }
+
+ public void validateScreenCapture() throws AWTException {
+ Robot robot = new Robot();
+ outputControlPanel = new JPanel(layout);
+ GridBagConstraints ogbc = new GridBagConstraints();
+
+ MultiResolutionImage image
+ = robot.createMultiResolutionScreenCapture(inputImageFrame.getBounds());
+ List imageList = image.getResolutionVariants();
+ int size = imageList.size();
+ BufferedImage lowResImage = (BufferedImage) imageList.get(0);
+ BufferedImage highResImage = (BufferedImage) imageList.get(1);
+
+ outputImageFrame = new JFrame("Output");
+ outputImageFrame.getContentPane().setLayout(new GridBagLayout());
+ ogbc.gridx = 0;
+ ogbc.gridy = 0;
+ ogbc.fill = GridBagConstraints.HORIZONTAL;
+ outputControlPanel.add(new JLabel(new ImageIcon(lowResImage)), ogbc);
+ int width = lowResImage.getWidth();
+ int height = lowResImage.getHeight();
+ JLabel labelImg1 = new JLabel("LEFT:Width: " + width
+ + " Height: " + height);
+ ogbc.gridx = 0;
+ ogbc.gridy = 1;
+ outputControlPanel.add(labelImg1, ogbc);
+ ogbc.gridx = 1;
+ ogbc.gridy = 0;
+ outputControlPanel.add(new JLabel(new ImageIcon(highResImage)), ogbc);
+ width = highResImage.getWidth();
+ height = highResImage.getHeight();
+ JLabel labelImg2 = new JLabel("RIGHT:Width: " + width
+ + " Height: " + height);
+ ogbc.gridx = 1;
+ ogbc.gridy = 1;
+ outputControlPanel.add(labelImg2, ogbc);
+ outputControlPanel.setBackground(Color.GRAY);
+ outputImageFrame.add(outputControlPanel);
+
+ outputImageFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ outputImageFrame.setBounds(600, 0, 400, 300);
+ outputImageFrame.setLocationRelativeTo(null);
+ outputImageFrame.setVisible(true);
+ }
+
+ public final void createUI() throws Exception {
+
+ mainFrame = new JFrame("ScreenCaptureResolutionTest");
+
+ layout = new GridBagLayout();
+ mainControlPanel = new JPanel(layout);
+ resultButtonPanel = new JPanel(layout);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ // Create Test instructions
+ String instructions
+ = "INSTRUCTIONS:"
+ + "\n Test to Visually validate MultiResolutionn Image. "
+ + "\n 1. Check if output window contains two screenshot "
+ + "\n of input window. "
+ + "\n 2. Right image should be twice the size of Left. "
+ + "\n 3. Quality of Right image should be better than Left. "
+ + "\n If all the three conditons are satisfied, then "
+ + "\n click pass else fail.";
+ instructionTextArea = new JTextArea();
+ instructionTextArea.setText(instructions);
+ instructionTextArea.setEnabled(false);
+ instructionTextArea.setDisabledTextColor(Color.black);
+ instructionTextArea.setBackground(Color.white);
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+
+ inputImagePanel = new JPanel(layout);
+ JLabel label = new JLabel("Resolution");
+ inputImagePanel.add(label);
+ inputImageFrame = new JFrame("Input");
+ inputImageFrame.add(inputImagePanel);
+
+ inputImageFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ inputImageFrame.setBounds(100, 200, 100, 100);
+ inputImageFrame.setVisible(true);
+
+ passButton = new JButton("Pass");
+ passButton.setActionCommand("Pass");
+ passButton.addActionListener((ActionEvent e) -> {
+ outputImageFrame.dispose();
+ inputImageFrame.dispose();
+ testResult = true;
+ mainFrame.dispose();
+ latch.countDown();
+
+ });
+ failButton = new JButton("Fail");
+ failButton.setActionCommand("Fail");
+ failButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ outputImageFrame.dispose();
+ inputImageFrame.dispose();
+ testResult = false;
+ mainFrame.dispose();
+ latch.countDown();
+ }
+ });
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ resultButtonPanel.add(passButton, gbc);
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+ mainFrame.pack();
+ mainFrame.setVisible(true);
+ }
+
+ public void disposeUI() {
+ outputImageFrame.dispose();
+ inputImageFrame.dispose();
+ mainFrame.setVisible(false);
+ mainFrame.dispose();
+ }
+
+}