mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-19 04:13:07 +00:00
410 lines
12 KiB
C
410 lines
12 KiB
C
/*
|
|
* Copyright (c) 2000, 2007, 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. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <jni.h>
|
|
#include <jlong.h>
|
|
#include "X11SurfaceData.h"
|
|
#include "Region.h"
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_sun_java2d_x11_X11PMBlitLoops_nativeBlit
|
|
(JNIEnv *env, jobject joSelf,
|
|
jlong srcData, jlong dstData,
|
|
jlong gc, jobject clip,
|
|
jint srcx, jint srcy,
|
|
jint dstx, jint dsty,
|
|
jint width, jint height)
|
|
{
|
|
#ifndef HEADLESS
|
|
X11SDOps *srcXsdo, *dstXsdo;
|
|
SurfaceDataBounds span, srcBounds;
|
|
RegionData clipInfo;
|
|
GC xgc;
|
|
|
|
if (width <= 0 || height <= 0) {
|
|
return;
|
|
}
|
|
|
|
srcXsdo = (X11SDOps *)jlong_to_ptr(srcData);
|
|
if (srcXsdo == NULL) {
|
|
return;
|
|
}
|
|
dstXsdo = (X11SDOps *)jlong_to_ptr(dstData);
|
|
if (dstXsdo == NULL) {
|
|
return;
|
|
}
|
|
if (Region_GetInfo(env, clip, &clipInfo)) {
|
|
return;
|
|
}
|
|
|
|
xgc = (GC)gc;
|
|
if (xgc == NULL) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MITSHM
|
|
if (srcXsdo->isPixmap) {
|
|
X11SD_UnPuntPixmap(srcXsdo);
|
|
}
|
|
#endif /* MITSHM */
|
|
|
|
/* clip the source rect to the source pixmap's dimensions */
|
|
srcBounds.x1 = srcx;
|
|
srcBounds.y1 = srcy;
|
|
srcBounds.x2 = srcx + width;
|
|
srcBounds.y2 = srcy + height;
|
|
SurfaceData_IntersectBoundsXYXY(&srcBounds,
|
|
0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight);
|
|
span.x1 = dstx;
|
|
span.y1 = dsty;
|
|
span.x2 = dstx + width;
|
|
span.y2 = dsty + height;
|
|
|
|
/* intersect the source and dest rects */
|
|
SurfaceData_IntersectBlitBounds(&srcBounds, &span,
|
|
dstx - srcx, dsty - srcy);
|
|
srcx = srcBounds.x1;
|
|
srcy = srcBounds.y1;
|
|
dstx = span.x1;
|
|
dsty = span.y1;
|
|
|
|
if (srcXsdo->bitmask != 0) {
|
|
XSetClipOrigin(awt_display, xgc, dstx - srcx, dsty - srcy);
|
|
XSetClipMask(awt_display, xgc, srcXsdo->bitmask);
|
|
}
|
|
|
|
Region_IntersectBounds(&clipInfo, &span);
|
|
if (!Region_IsEmpty(&clipInfo)) {
|
|
Region_StartIteration(env, &clipInfo);
|
|
srcx -= dstx;
|
|
srcy -= dsty;
|
|
while (Region_NextIteration(&clipInfo, &span)) {
|
|
XCopyArea(awt_display, srcXsdo->drawable, dstXsdo->drawable, xgc,
|
|
srcx + span.x1, srcy + span.y1,
|
|
span.x2 - span.x1, span.y2 - span.y1,
|
|
span.x1, span.y1);
|
|
}
|
|
Region_EndIteration(env, &clipInfo);
|
|
}
|
|
|
|
if (srcXsdo->bitmask != 0) {
|
|
XSetClipMask(awt_display, xgc, None);
|
|
}
|
|
|
|
#ifdef MITSHM
|
|
if (srcXsdo->shmPMData.usingShmPixmap) {
|
|
srcXsdo->shmPMData.xRequestSent = JNI_TRUE;
|
|
}
|
|
#endif /* MITSHM */
|
|
X11SD_DirectRenderNotify(env, dstXsdo);
|
|
#endif /* !HEADLESS */
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_sun_java2d_x11_X11PMBlitBgLoops_nativeBlitBg
|
|
(JNIEnv *env, jobject joSelf,
|
|
jlong srcData, jlong dstData,
|
|
jlong xgc, jint pixel,
|
|
jint srcx, jint srcy,
|
|
jint dstx, jint dsty,
|
|
jint width, jint height)
|
|
{
|
|
#ifndef HEADLESS
|
|
X11SDOps *srcXsdo, *dstXsdo;
|
|
GC dstGC;
|
|
SurfaceDataBounds dstBounds, srcBounds;
|
|
Drawable srcDrawable;
|
|
|
|
if (width <= 0 || height <= 0) {
|
|
return;
|
|
}
|
|
|
|
srcXsdo = (X11SDOps *)jlong_to_ptr(srcData);
|
|
if (srcXsdo == NULL) {
|
|
return;
|
|
}
|
|
dstXsdo = (X11SDOps *)jlong_to_ptr(dstData);
|
|
if (dstXsdo == NULL) {
|
|
return;
|
|
}
|
|
|
|
dstGC = (GC)xgc;
|
|
if (dstGC == NULL) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MITSHM
|
|
if (srcXsdo->isPixmap) {
|
|
X11SD_UnPuntPixmap(srcXsdo);
|
|
}
|
|
#endif /* MITSHM */
|
|
|
|
srcDrawable = srcXsdo->GetPixmapWithBg(env, srcXsdo, pixel);
|
|
if (srcDrawable == 0) {
|
|
return;
|
|
}
|
|
|
|
/* clip the source rect to the source pixmap's dimensions */
|
|
srcBounds.x1 = srcx;
|
|
srcBounds.y1 = srcy;
|
|
srcBounds.x2 = srcx + width;
|
|
srcBounds.y2 = srcy + height;
|
|
SurfaceData_IntersectBoundsXYXY(&srcBounds,
|
|
0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight);
|
|
dstBounds.x1 = dstx;
|
|
dstBounds.y1 = dsty;
|
|
dstBounds.x2 = dstx + width;
|
|
dstBounds.y2 = dsty + height;
|
|
|
|
/* intersect the source and dest rects */
|
|
SurfaceData_IntersectBlitBounds(&srcBounds, &dstBounds,
|
|
dstx - srcx, dsty - srcy);
|
|
srcx = srcBounds.x1;
|
|
srcy = srcBounds.y1;
|
|
dstx = dstBounds.x1;
|
|
dsty = dstBounds.y1;
|
|
width = srcBounds.x2 - srcBounds.x1;
|
|
height = srcBounds.y2 - srcBounds.y1;
|
|
|
|
/* do an unmasked copy as we've already filled transparent
|
|
pixels of the source image with the desired color */
|
|
XCopyArea(awt_display, srcDrawable, dstXsdo->drawable, dstGC,
|
|
srcx, srcy, width, height, dstx, dsty);
|
|
|
|
srcXsdo->ReleasePixmapWithBg(env, srcXsdo);
|
|
X11SD_DirectRenderNotify(env, dstXsdo);
|
|
#endif /* !HEADLESS */
|
|
}
|
|
|
|
/*
|
|
* Class: sun_java2d_x11_X11PMBlitLoops
|
|
* Method: updateBitmask
|
|
* Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;)V
|
|
*/
|
|
JNIEXPORT void JNICALL
|
|
Java_sun_java2d_x11_X11PMBlitLoops_updateBitmask
|
|
(JNIEnv *env, jclass xpmbl, jobject srcsd, jobject dstsd, jboolean isICM)
|
|
{
|
|
#ifndef HEADLESS
|
|
SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcsd);
|
|
X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, dstsd);
|
|
SurfaceDataRasInfo srcInfo;
|
|
|
|
int flags;
|
|
int screen;
|
|
int width;
|
|
int height;
|
|
jint srcScan, dstScan;
|
|
int rowCount;
|
|
unsigned char *pDst;
|
|
XImage *image;
|
|
GC xgc;
|
|
|
|
if (srcOps == NULL || xsdo == NULL) {
|
|
JNU_ThrowNullPointerException(env, "Null BISD in updateMaskRegion");
|
|
return;
|
|
}
|
|
|
|
AWT_LOCK();
|
|
|
|
screen = xsdo->configData->awt_visInfo.screen;
|
|
width = xsdo->pmWidth;
|
|
height = xsdo->pmHeight;
|
|
|
|
if (xsdo->bitmask == 0) {
|
|
/* create the bitmask if it is not yet created */
|
|
xsdo->bitmask = XCreatePixmap(awt_display,
|
|
RootWindow(awt_display, screen),
|
|
width, height, 1);
|
|
if (xsdo->bitmask == 0) {
|
|
AWT_UNLOCK();
|
|
if (!(*env)->ExceptionCheck(env))
|
|
{
|
|
JNU_ThrowOutOfMemoryError(env,
|
|
"Cannot create bitmask for "
|
|
"offscreen surface");
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Create a bitmask image and then blit it to the pixmap. */
|
|
image = XCreateImage(awt_display, DefaultVisual(awt_display, screen),
|
|
1, XYBitmap, 0, NULL, width, height, 32, 0);
|
|
if (image == NULL) {
|
|
AWT_UNLOCK();
|
|
if (!(*env)->ExceptionCheck(env))
|
|
{
|
|
JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
|
|
}
|
|
return;
|
|
}
|
|
dstScan = image->bytes_per_line;
|
|
image->data = malloc((size_t) dstScan * height);
|
|
if (image->data == NULL) {
|
|
XFree(image);
|
|
AWT_UNLOCK();
|
|
if (!(*env)->ExceptionCheck(env))
|
|
{
|
|
JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
|
|
}
|
|
return;
|
|
}
|
|
pDst = (unsigned char *)image->data;
|
|
|
|
srcInfo.bounds.x1 = 0;
|
|
srcInfo.bounds.y1 = 0;
|
|
srcInfo.bounds.x2 = width;
|
|
srcInfo.bounds.y2 = height;
|
|
|
|
flags = (isICM ? (SD_LOCK_LUT | SD_LOCK_READ) : SD_LOCK_READ);
|
|
if (srcOps->Lock(env, srcOps, &srcInfo, flags) != SD_SUCCESS) {
|
|
XDestroyImage(image);
|
|
AWT_UNLOCK();
|
|
return;
|
|
}
|
|
srcOps->GetRasInfo(env, srcOps, &srcInfo);
|
|
|
|
rowCount = height;
|
|
if (isICM) {
|
|
unsigned char *pSrc;
|
|
jint *srcLut;
|
|
|
|
srcScan = srcInfo.scanStride;
|
|
srcLut = srcInfo.lutBase;
|
|
pSrc = (unsigned char *)srcInfo.rasBase;
|
|
|
|
if (image->bitmap_bit_order == MSBFirst) {
|
|
do {
|
|
int x = 0, bx = 0;
|
|
unsigned int pix = 0;
|
|
unsigned int bit = 0x80;
|
|
unsigned char *srcPixel = pSrc;
|
|
do {
|
|
if (bit == 0) {
|
|
pDst[bx++] = (unsigned char)pix;
|
|
pix = 0;
|
|
bit = 0x80;
|
|
}
|
|
pix |= bit & (srcLut[*srcPixel++] >> 31);
|
|
bit >>= 1;
|
|
} while (++x < width);
|
|
pDst[bx] = (unsigned char)pix;
|
|
pDst += dstScan;
|
|
pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
|
|
} while (--rowCount > 0);
|
|
} else {
|
|
do {
|
|
int x = 0, bx = 0;
|
|
unsigned int pix = 0;
|
|
unsigned int bit = 1;
|
|
unsigned char *srcPixel = pSrc;
|
|
do {
|
|
if ((bit >> 8) != 0) {
|
|
pDst[bx++] = (unsigned char) pix;
|
|
pix = 0;
|
|
bit = 1;
|
|
}
|
|
pix |= bit & (srcLut[*srcPixel++] >> 31);
|
|
bit <<= 1;
|
|
} while (++x < width);
|
|
pDst[bx] = (unsigned char) pix;
|
|
pDst += dstScan;
|
|
pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
|
|
} while (--rowCount > 0);
|
|
}
|
|
} else /*DCM with ARGB*/ {
|
|
unsigned int *pSrc;
|
|
|
|
/* this is a number of pixels in a row, not number of bytes */
|
|
srcScan = srcInfo.scanStride;
|
|
pSrc = (unsigned int *)srcInfo.rasBase;
|
|
|
|
if (image->bitmap_bit_order == MSBFirst) {
|
|
do {
|
|
int x = 0, bx = 0;
|
|
unsigned int pix = 0;
|
|
unsigned int bit = 0x80;
|
|
int *srcPixel = (int *) pSrc;
|
|
do {
|
|
if (bit == 0) {
|
|
/* next word */
|
|
pDst[bx++] = (unsigned char)pix;
|
|
pix = 0;
|
|
bit = 0x80;
|
|
}
|
|
if (*srcPixel++ & 0xff000000) {
|
|
/* if src pixel is opaque, set the bit in the bitmap */
|
|
pix |= bit;
|
|
}
|
|
bit >>= 1;
|
|
} while (++x < width);
|
|
/* last pixels in a row */
|
|
pDst[bx] = (unsigned char)pix;
|
|
|
|
pDst += dstScan;
|
|
pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
|
|
} while (--rowCount > 0);
|
|
} else {
|
|
do {
|
|
int x = 0, bx = 0;
|
|
unsigned int pix = 0;
|
|
unsigned int bit = 1;
|
|
int *srcPixel = (int *) pSrc;
|
|
do {
|
|
if ((bit >> 8) != 0) {
|
|
pDst[bx++] = (unsigned char)pix;
|
|
pix = 0;
|
|
bit = 1;
|
|
}
|
|
if (*srcPixel++ & 0xff000000) {
|
|
/* if src pixel is opaque, set the bit in the bitmap */
|
|
pix |= bit;
|
|
}
|
|
bit <<= 1;
|
|
} while (++x < width);
|
|
pDst[bx] = (unsigned char)pix;
|
|
pDst += dstScan;
|
|
pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
|
|
} while (--rowCount > 0);
|
|
}
|
|
}
|
|
SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
|
|
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
|
|
|
|
xgc = XCreateGC(awt_display, xsdo->bitmask, 0L, NULL);
|
|
XSetForeground(awt_display, xgc, 1);
|
|
XSetBackground(awt_display, xgc, 0);
|
|
XPutImage(awt_display, xsdo->bitmask, xgc,
|
|
image, 0, 0, 0, 0, width, height);
|
|
|
|
XFreeGC(awt_display, xgc);
|
|
XDestroyImage(image);
|
|
|
|
AWT_UNLOCK();
|
|
#endif /* !HEADLESS */
|
|
}
|