changeset 9977:89a5de54b7dc

8162783: [Windows] HiDPI screenshot artifacts using glass Robot Reviewed-by: flar
author kcr
date Wed, 10 Aug 2016 09:44:29 -0700
parents 1eef8c77716a
children 2be9baaa3ee0
files modules/javafx.graphics/src/main/java/com/sun/glass/ui/Robot.java modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkRobot.java modules/javafx.graphics/src/main/java/com/sun/glass/ui/lens/LensRobot.java modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinRobot.java modules/javafx.graphics/src/main/native-glass/win/Robot.cpp
diffstat 5 files changed, 102 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Robot.java	Tue Aug 09 11:15:27 2016 +0300
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/Robot.java	Wed Aug 10 09:44:29 2016 -0700
@@ -25,6 +25,7 @@
 package com.sun.glass.ui;
 
 import static com.sun.javafx.FXPermissions.CREATE_ROBOT_PERMISSION;
+import java.nio.IntBuffer;
 
 public abstract class Robot {
 
@@ -140,7 +141,59 @@
         return _getPixelColor(x, y);
     }
 
-    protected abstract Pixels _getScreenCapture(int x, int y, int width, int height, boolean isHiDPI);
+    // Subclasses must override and implement at least one of the following two
+    // _getScreenCapture methods
+
+    protected void _getScreenCapture(int x, int y, int width, int height, int[] data) {
+        throw new UnsupportedOperationException("Not implementated in the base class");
+    }
+
+    protected Pixels _getScreenCapture(int x, int y, int width, int height, boolean isHiDPI) {
+        Screen mainScreen = Screen.getMainScreen();
+        float uiScaleX = mainScreen.getPlatformScaleX();
+        float uiScaleY = mainScreen.getPlatformScaleY();
+        int data[];
+        int dw, dh;
+        if (uiScaleX == 1.0f && uiScaleY == 1.0f) {
+            data = new int[width * height];
+            _getScreenCapture(x, y, width, height, data);
+            dw = width;
+            dh = height;
+        } else {
+            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 tmpdata[] = new int[pwidth * pheight];
+            _getScreenCapture(pminx, pminy, pwidth, pheight, tmpdata);
+            if (isHiDPI) {
+                data = tmpdata;
+                dw = pwidth;
+                dh = pheight;
+            } else {
+                data = new int[width * height];
+                int index = 0;
+                for (int iy = 0; iy < height; iy++) {
+                    float rely = ((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 = ((x + ix + 0.5f) * uiScaleX) - (pminx + 0.5f);
+                        int irelx = (int) Math.floor(relx);
+                        int fractx = (int) ((relx - irelx) * 256);
+                        data[index++] =
+                            interp(tmpdata, irelx, irely, pwidth, pheight, fractx, fracty);
+                    }
+                }
+                dw = width;
+                dh = height;
+            }
+        }
+        return Application.GetApplication().createPixels(dw, dh, IntBuffer.wrap(data));
+    }
+
     /**
      * Returns a capture of the specified rectangular area of the screen.
      *
@@ -170,4 +223,48 @@
     public Pixels getScreenCapture(int x, int y, int width, int height) {
         return getScreenCapture(x, y, width, height, false);
     }
+
+    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;
+    }
 }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkRobot.java	Tue Aug 09 11:15:27 2016 +0300
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkRobot.java	Wed Aug 10 09:44:29 2016 -0700
@@ -73,94 +73,5 @@
         return result[0];
     }
 
-    native private void _getScreenCapture(int x, int y, int width, int height, int[] data);
-    @Override protected Pixels _getScreenCapture(int x, int y, int width, int height, boolean isHiDPI) {
-        Screen mainScreen = Screen.getMainScreen();
-        float uiScaleX = mainScreen.getPlatformScaleX();
-        float uiScaleY = mainScreen.getPlatformScaleY();
-        int data[];
-        int dw, dh;
-        if (uiScaleX == 1.0f && uiScaleY == 1.0f) {
-            data = new int[width * height];
-            _getScreenCapture(x, y, width, height, data);
-            dw = width;
-            dh = height;
-        } else {
-            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 tmpdata[] = new int[pwidth * pheight];
-            _getScreenCapture(pminx, pminy, pwidth, pheight, tmpdata);
-            if (isHiDPI) {
-                data = tmpdata;
-                dw = pwidth;
-                dh = pheight;
-            } else {
-                data = new int[width * height];
-                int index = 0;
-                for (int iy = 0; iy < height; iy++) {
-                    float rely = ((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 = ((x + ix + 0.5f) * uiScaleX) - (pminx + 0.5f);
-                        int irelx = (int) Math.floor(relx);
-                        int fractx = (int) ((relx - irelx) * 256);
-                        data[index++] =
-                            interp(tmpdata, irelx, irely, pwidth, pheight, fractx, fracty);
-                    }
-                }
-                dw = width;
-                dh = height;
-            }
-        }
-        return Application.GetApplication().createPixels(dw, dh, IntBuffer.wrap(data));
-    }
-
-    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);
-        }
-    }
-
-    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;
-    }
+    @Override native protected void _getScreenCapture(int x, int y, int width, int height, int[] data);
 }
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/lens/LensRobot.java	Tue Aug 09 11:15:27 2016 +0300
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/lens/LensRobot.java	Wed Aug 10 09:44:29 2016 -0700
@@ -105,7 +105,7 @@
 
     @Override native protected int _getPixelColor(int x, int y);
 
-    native private void _getScreenCapture(int x, int y, int width, int height, int[] data);
+    @Override native protected void _getScreenCapture(int x, int y, int width, int height, int[] data);
     @Override protected Pixels _getScreenCapture(int x, int y, int width, int height, boolean isHiDPI) {
         int data[] = new int[width * height];
         _getScreenCapture(x, y, width, height, data);
--- a/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinRobot.java	Tue Aug 09 11:15:27 2016 +0300
+++ b/modules/javafx.graphics/src/main/java/com/sun/glass/ui/win/WinRobot.java	Wed Aug 10 09:44:29 2016 -0700
@@ -51,12 +51,5 @@
     @Override native protected int _getMouseY();
 
     @Override native protected int _getPixelColor(int x, int y);
-    native private void _getScreenCapture(int x, int y, int width, int height, int[] data);
-    @Override protected Pixels _getScreenCapture(int x, int y, int width, int height, boolean isHiDPI) {
-        int data[] = new int[width * height];
-        _getScreenCapture(x, y, width, height, data);
-        return Application.GetApplication().createPixels(width, height, IntBuffer.wrap(data));
-    }
-
+    @Override native protected void _getScreenCapture(int x, int y, int width, int height, int[] data);
 }
-
--- a/modules/javafx.graphics/src/main/native-glass/win/Robot.cpp	Tue Aug 09 11:15:27 2016 +0300
+++ b/modules/javafx.graphics/src/main/native-glass/win/Robot.cpp	Wed Aug 10 09:44:29 2016 -0700
@@ -300,17 +300,6 @@
 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinRobot__1getScreenCapture
     (JNIEnv *env, jobject jrobot, jint x, jint y, jint width, jint height, jintArray pixelArray)
 {
-    jfloat fx = (jfloat) x;
-    jfloat fy = (jfloat) y;
-    GlassScreen::FX2Win(&fx, &fy);
-    jint dx = (jint) ceil(fx - 0.5f);
-    jint dy = (jint) ceil(fy - 0.5f);
-    fx = (jfloat) (x + width);
-    fy = (jfloat) (y + height);
-    GlassScreen::FX2Win(&fx, &fy);
-    jint dw = ((jint) ceil(fx - 0.5f)) - dx;
-    jint dh = ((jint) ceil(fy - 0.5f)) - dy;
-
     int numPixels = width * height;
     int pixelDataSize = sizeof(jint) * numPixels;
     ASSERT(pixelDataSize > 0 && pixelDataSize % 4 == 0);
@@ -318,7 +307,7 @@
     jint * pixelData = (jint *)(new BYTE[pixelDataSize]);
 
     if (pixelData) {
-        GetScreenCapture(dx, dy, dw, dh, pixelData, width, height);
+        GetScreenCapture(x, y, width, height, pixelData, width, height);
 
         // copy pixels into Java array
         env->SetIntArrayRegion(pixelArray, 0, numPixels, pixelData);