--- old/src/java.desktop/share/classes/java/awt/Robot.java 2016-11-02 16:05:02.001980999 +0530 +++ new/src/java.desktop/share/classes/java/awt/Robot.java 2016-11-02 16:05:01.809885000 +0530 @@ -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; @@ -394,6 +396,167 @@ return color; } + private static int interp(int pixels[], int x, int y, int w, int h, + int fractx1, int fracty1) { + int fractx0 = 256 - fractx1; + int fracty0 = 256 - fracty1; + int i = y * w + x; + int rgb00 = (x < 0 || y < 0 || x >= w || y >= h) ? 0 : pixels[i]; + if (fracty1 == 0) { + // No interplation with pixels[y+1] + if (fractx1 == 0) { + // No interpolation with any neighbors + return rgb00; + } + int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1]; + return interp(rgb00, rgb10, fractx0, fractx1); + } else if (fractx1 == 0) { + // No interpolation with pixels[x+1] + int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w]; + return interp(rgb00, rgb01, fracty0, fracty1); + } else { + // All 4 neighbors must be interpolated + int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1]; + int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w]; + int rgb11 = (x + 1 >= w || y + 1 >= h) ? 0 : pixels[i + w + 1]; + return interp(interp(rgb00, rgb10, fractx0, fractx1), + interp(rgb01, rgb11, fractx0, fractx1), + fracty0, fracty1); + } + } + + private static int interp(int rgb0, int rgb1, int fract0, int fract1) { + int a0 = (rgb0 >> 24) & 0xff; + int r0 = (rgb0 >> 16) & 0xff; + int g0 = (rgb0 >> 8) & 0xff; + int b0 = (rgb0) & 0xff; + int a1 = (rgb1 >> 24) & 0xff; + int r1 = (rgb1 >> 16) & 0xff; + int g1 = (rgb1 >> 8) & 0xff; + int b1 = (rgb1) & 0xff; + int a = (a0 * fract0 + a1 * fract1) >> 8; + int r = (r0 * fract0 + r1 * fract1) >> 8; + int g = (g0 * fract0 + g1 * fract1) >> 8; + int b = (b0 * fract0 + b1 * fract1) >> 8; + return (a << 24) | (r << 16) | (g << 8) | b; + } + + /** + * 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 + * @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 createHiDPIScreenCapture(Rectangle screenRect) { + checkScreenCaptureAllowed(); + + checkValidRect(screenRect); + + BufferedImage lowResolutionImage; + BufferedImage highResolutionImage; + DataBufferInt buffer; + WritableRaster raster; + + if (screenCapCM == null) { + /* + * Fix for 4285201 + * Create a DirectColorModel equivalent to the default RGB ColorModel, + * except with no Alpha component. + */ + + screenCapCM = new DirectColorModel(24, + /* 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[]; + + // Return normal screenCapture for Non-HiDPI Display + if(uiScaleX ==1 && uiScaleY==1){ + return createScreenCapture(screenRect); + } + + 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 rect = new Rectangle(pminx, pminy, pwidth, pheight); + temppixels = peer.getRGBPixels(rect); + + // HighResolutionImage + pixels = temppixels; + screenRect = rect; + + buffer = new DataBufferInt(pixels, pixels.length); + raster = Raster.createPackedRaster(buffer, screenRect.width, + screenRect.height, screenRect.width, bandmasks, null); + SunWritableRaster.makeTrackable(buffer); + + highResolutionImage = new BufferedImage(screenCapCM, raster, false, null); + + // LowResolutionImage + pixels = new int[width * height]; + int index = 0; + for (int iy = 0; iy < height; iy++) { + float rely = (float) (((y + iy + 0.5f) * uiScaleY) + - (pminy + 0.5f)); + int irely = (int) Math.floor(rely); + int fracty = (int) ((rely - irely) * 256); + for (int ix = 0; ix < width; ix++) { + float relx = (float) (((x + ix + 0.5f) * uiScaleX) + - (pminx + 0.5f)); + int irelx = (int) Math.floor(relx); + int fractx = (int) ((relx - irelx) * 256); + pixels[index++] + = interp(temppixels, irelx, irely, pwidth, + pheight, fractx, fracty); + } + } + screenRect.width = width; + screenRect.height = height; + + buffer = new DataBufferInt(pixels, pixels.length); + raster = Raster.createPackedRaster(buffer, screenRect.width, + screenRect.height, screenRect.width, bandmasks, null); + SunWritableRaster.makeTrackable(buffer); + + lowResolutionImage = new BufferedImage(screenCapCM, raster, false, null); + + // MultiResoltuionImage + BaseMultiResolutionImage image = new BaseMultiResolutionImage( + lowResolutionImage,highResolutionImage); + + return image; + } + /** * Creates an image containing pixels read from the screen. This image does * not include the mouse cursor.