JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, jclass cls, jobject xgc, jint x, jint y, jint width, jint height, jintArray pixelArray) { XImage *image; jint *ary; /* Array of jints for sending pixel values back * to parent process. */ Window rootWindow; AwtGraphicsConfigDataPtr adata; DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray); AWT_LOCK(); /* avoid a lot of work for empty rectangles */ if ((width * height) == 0) { AWT_UNLOCK(); return; } DASSERT(width * height > 0); /* only allow positive size */ adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData); DASSERT(adata != NULL); rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen); image = getWindowImage(awt_display, rootWindow, x, y, width, height); /* Array to use to crunch around the pixel values */ ary = (jint *) malloc(width * height * sizeof (jint)); if (ary == NULL) { JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); XDestroyImage(image); AWT_UNLOCK(); return; } /* convert to Java ARGB pixels */ for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { jint pixel = (jint) XGetPixel(image, x, y); /* Note ignore upper * 32-bits on 64-bit * OSes. */ pixel |= 0xff000000; /* alpha - full opacity */ ary[(y * width) + x] = pixel; } } (*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary); free(ary); XDestroyImage(image); AWT_UNLOCK(); }
JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, jclass cls, jobject xgc, jint jx, jint jy, jint jwidth, jint jheight, jint scale, jintArray pixelArray, jboolean useGtk) { XImage *image; jint *ary; /* Array of jints for sending pixel values back * to parent process. */ Window rootWindow; XWindowAttributes attr; AwtGraphicsConfigDataPtr adata; DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, jx, jy, jwidth, jheight, pixelArray); if (jwidth <= 0 || jheight <= 0) { return; } adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData); DASSERT(adata != NULL); 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) { if (hasXCompositeOverlayExtension(awt_display) && isXCompositeDisplay(awt_display, adata->awt_visInfo.screen)) { rootWindow = compositeGetOverlayWindow(awt_display, rootWindow); } } if (!XGetWindowAttributes(awt_display, rootWindow, &attr) || sx + swidth <= attr.x || attr.x + attr.width <= sx || sy + sheight <= attr.y || attr.y + attr.height <= sy) { AWT_UNLOCK(); return; // Does not intersect with root window } 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; int dx = attr.x > sx ? attr.x - sx : 0; int dy = attr.y > sy ? attr.y - sy : 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); gtk->gdk_threads_leave(); } if (gtk_failed) { image = getWindowImage(awt_display, rootWindow, sx, sy, swidth, sheight); ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); if (!ary) { XDestroyImage(image); AWT_UNLOCK(); 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); /* Note ignore upper * 32-bits on 64-bit * OSes. */ pixel |= 0xff000000; /* alpha - full opacity */ index = (_y + dy) * jwidth + (_x + dx); ary[index] = pixel; } } XDestroyImage(image); (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); } AWT_UNLOCK(); }