--- old/src/java.desktop/share/classes/java/awt/Robot.java 2016-11-16 11:00:58.155850000 +0530 +++ new/src/java.desktop/share/classes/java/awt/Robot.java 2016-11-16 11:00:57.943743999 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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,8 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import java.awt.geom.AffineTransform; +import java.awt.image.BaseMultiResolutionImage; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.awt.image.DirectColorModel; @@ -393,7 +395,7 @@ Color color = new Color(peer.getRGBPixel(x, y)); return color; } - + /** * Creates an image containing pixels read from the screen. This image does * not include the mouse cursor. @@ -405,11 +407,30 @@ * @see AWTPermission */ public synchronized BufferedImage createScreenCapture(Rectangle screenRect) { + return (BufferedImage) createScreenCapture(screenRect, false); + } + + /** + * Creates an image containing pixels read from the screen. + * This image does not include the mouse cursor. + * Returns BufferedImage for Non-HiDPI display and MultiResolutionImage + * for HiDPI display with two resolution variants. + * @param screenRect Rect to capture in screen coordinates + * @param isHiDPI Indicate if HiDPI Display + * @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 Image createScreenCapture(Rectangle screenRect, boolean isHiDPI) { checkScreenCaptureAllowed(); checkValidRect(screenRect); - BufferedImage image; + BufferedImage lowResolutionImage; + BufferedImage highResolutionImage; DataBufferInt buffer; WritableRaster raster; @@ -421,31 +442,90 @@ */ screenCapCM = new DirectColorModel(24, - /* red mask */ 0x00FF0000, - /* green mask */ 0x0000FF00, - /* blue mask */ 0x000000FF); + /* red mask */ 0x00FF0000, + /* green mask */ 0x0000FF00, + /* blue mask */ 0x000000FF); } - // need to sync the toolkit prior to grabbing the pixels since in some - // cases rendering to the screen may be delayed - Toolkit.getDefaultToolkit().sync(); - - int pixels[]; int[] bandmasks = new int[3]; - - pixels = peer.getRGBPixels(screenRect); - buffer = new DataBufferInt(pixels, pixels.length); - 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[]; - raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null); - SunWritableRaster.makeTrackable(buffer); - - image = new BufferedImage(screenCapCM, raster, false, null); - - return image; + if (uiScaleX == 1 && uiScaleY == 1) { + pixels = peer.getRGBPixels(screenRect); + buffer = new DataBufferInt(pixels, pixels.length); + + 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); + + return new BufferedImage(screenCapCM, raster, false, null); + + } else { + + int x = screenRect.x; + int y = screenRect.y; + int width = screenRect.width; + int height = screenRect.height; + int pminx = (int) Math.floor(x * uiScaleX); + int pminy = (int) Math.floor(y * uiScaleY); + int pmaxx = (int) Math.ceil((x + width) * uiScaleX); + int pmaxy = (int) Math.ceil((y + height) * uiScaleY); + int pwidth = pmaxx - pminx; + int pheight = pmaxy - pminy; + int temppixels[]; + Rectangle scaledRect = new Rectangle(pminx, pminy, pwidth, pheight); + 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, screenRect.x, screenRect.y, + screenRect.width, screenRect.height, + scaledRect.x, scaledRect.y, + scaledRect.width, scaledRect.height, null); + g.dispose(); + + if (!isHiDPI) { + return lowResolutionImage; + } else { + // MultiResoltuionImage + return new BaseMultiResolutionImage( + lowResolutionImage, highResolutionImage); + } + } } private static void checkValidRect(Rectangle rect) { --- old/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp 2016-11-16 11:00:58.748145999 +0530 +++ new/src/java.desktop/windows/native/libawt/windows/awt_Robot.cpp 2016-11-16 11:00:58.516030000 +0530 @@ -224,24 +224,12 @@ 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;