1 /*
   2  * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdlib.h>
  27 #include <jni.h>
  28 #include <jlong.h>
  29 #include "X11SurfaceData.h"
  30 #include "Region.h"
  31 
  32 JNIEXPORT void JNICALL
  33 Java_sun_java2d_x11_X11PMBlitLoops_nativeBlit
  34     (JNIEnv *env, jobject joSelf,
  35      jlong srcData, jlong dstData,
  36      jlong gc, jobject clip,
  37      jint srcx, jint srcy,
  38      jint dstx, jint dsty,
  39      jint width, jint height)
  40 {
  41 #ifndef HEADLESS
  42     X11SDOps *srcXsdo, *dstXsdo;
  43     SurfaceDataBounds span, srcBounds;
  44     RegionData clipInfo;
  45     GC xgc;
  46 
  47     if (width <= 0 || height <= 0) {
  48         return;
  49     }
  50 
  51     srcXsdo = (X11SDOps *)jlong_to_ptr(srcData);
  52     if (srcXsdo == NULL) {
  53         return;
  54     }
  55     dstXsdo = (X11SDOps *)jlong_to_ptr(dstData);
  56     if (dstXsdo == NULL) {
  57         return;
  58     }
  59     if (Region_GetInfo(env, clip, &clipInfo)) {
  60         return;
  61     }
  62 
  63     xgc = (GC)gc;
  64     if (xgc == NULL) {
  65         return;
  66     }
  67 
  68 #ifdef MITSHM
  69     if (srcXsdo->isPixmap) {
  70         X11SD_UnPuntPixmap(srcXsdo);
  71     }
  72 #endif /* MITSHM */
  73 
  74     /* clip the source rect to the source pixmap's dimensions */
  75     srcBounds.x1 = srcx;
  76     srcBounds.y1 = srcy;
  77     srcBounds.x2 = srcx + width;
  78     srcBounds.y2 = srcy + height;
  79     SurfaceData_IntersectBoundsXYXY(&srcBounds,
  80                                     0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight);
  81     span.x1 = dstx;
  82     span.y1 = dsty;
  83     span.x2 = dstx + width;
  84     span.y2 = dsty + height;
  85 
  86     /* intersect the source and dest rects */
  87     SurfaceData_IntersectBlitBounds(&srcBounds, &span,
  88                                     dstx - srcx, dsty - srcy);
  89     srcx = srcBounds.x1;
  90     srcy = srcBounds.y1;
  91     dstx = span.x1;
  92     dsty = span.y1;
  93 
  94     if (srcXsdo->bitmask != 0) {
  95         XSetClipOrigin(awt_display, xgc, dstx - srcx, dsty - srcy);
  96         XSetClipMask(awt_display, xgc, srcXsdo->bitmask);
  97     }
  98 
  99     Region_IntersectBounds(&clipInfo, &span);
 100     if (!Region_IsEmpty(&clipInfo)) {
 101         Region_StartIteration(env, &clipInfo);
 102         srcx -= dstx;
 103         srcy -= dsty;
 104         while (Region_NextIteration(&clipInfo, &span)) {
 105             XCopyArea(awt_display, srcXsdo->drawable, dstXsdo->drawable, xgc,
 106                       srcx + span.x1, srcy + span.y1,
 107                       span.x2 - span.x1, span.y2 - span.y1,
 108                       span.x1, span.y1);
 109         }
 110         Region_EndIteration(env, &clipInfo);
 111     }
 112 
 113     if (srcXsdo->bitmask != 0) {
 114         XSetClipMask(awt_display, xgc, None);
 115     }
 116 
 117 #ifdef MITSHM
 118     if (srcXsdo->shmPMData.usingShmPixmap) {
 119         srcXsdo->shmPMData.xRequestSent = JNI_TRUE;
 120     }
 121 #endif /* MITSHM */
 122     X11SD_DirectRenderNotify(env, dstXsdo);
 123 #endif /* !HEADLESS */
 124 }
 125 
 126 JNIEXPORT void JNICALL
 127 Java_sun_java2d_x11_X11PMBlitBgLoops_nativeBlitBg
 128     (JNIEnv *env, jobject joSelf,
 129      jlong srcData, jlong dstData,
 130      jlong xgc, jint pixel,
 131      jint srcx, jint srcy,
 132      jint dstx, jint dsty,
 133      jint width, jint height)
 134 {
 135 #ifndef HEADLESS
 136     X11SDOps *srcXsdo, *dstXsdo;
 137     GC dstGC;
 138     SurfaceDataBounds dstBounds, srcBounds;
 139     Drawable srcDrawable;
 140 
 141     if (width <= 0 || height <= 0) {
 142         return;
 143     }
 144 
 145     srcXsdo = (X11SDOps *)jlong_to_ptr(srcData);
 146     if (srcXsdo == NULL) {
 147         return;
 148     }
 149     dstXsdo = (X11SDOps *)jlong_to_ptr(dstData);
 150     if (dstXsdo == NULL) {
 151         return;
 152     }
 153 
 154     dstGC = (GC)xgc;
 155     if (dstGC == NULL) {
 156         return;
 157     }
 158 
 159 #ifdef MITSHM
 160     if (srcXsdo->isPixmap) {
 161         X11SD_UnPuntPixmap(srcXsdo);
 162     }
 163 #endif /* MITSHM */
 164 
 165     srcDrawable = srcXsdo->GetPixmapWithBg(env, srcXsdo, pixel);
 166     if (srcDrawable == 0) {
 167         return;
 168     }
 169 
 170     /* clip the source rect to the source pixmap's dimensions */
 171     srcBounds.x1 = srcx;
 172     srcBounds.y1 = srcy;
 173     srcBounds.x2 = srcx + width;
 174     srcBounds.y2 = srcy + height;
 175     SurfaceData_IntersectBoundsXYXY(&srcBounds,
 176                                     0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight);
 177     dstBounds.x1 = dstx;
 178     dstBounds.y1 = dsty;
 179     dstBounds.x2 = dstx + width;
 180     dstBounds.y2 = dsty + height;
 181 
 182     /* intersect the source and dest rects */
 183     SurfaceData_IntersectBlitBounds(&srcBounds, &dstBounds,
 184                                     dstx - srcx, dsty - srcy);
 185     srcx = srcBounds.x1;
 186     srcy = srcBounds.y1;
 187     dstx = dstBounds.x1;
 188     dsty = dstBounds.y1;
 189     width = srcBounds.x2 - srcBounds.x1;
 190     height = srcBounds.y2 - srcBounds.y1;
 191 
 192     /* do an unmasked copy as we've already filled transparent
 193        pixels of the source image with the desired color */
 194     XCopyArea(awt_display, srcDrawable, dstXsdo->drawable, dstGC,
 195               srcx, srcy, width, height, dstx, dsty);
 196 
 197     srcXsdo->ReleasePixmapWithBg(env, srcXsdo);
 198     X11SD_DirectRenderNotify(env, dstXsdo);
 199 #endif /* !HEADLESS */
 200 }
 201 
 202 /*
 203  * Class:     sun_java2d_x11_X11PMBlitLoops
 204  * Method:    updateBitmask
 205  * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;)V
 206  */
 207 JNIEXPORT void JNICALL
 208 Java_sun_java2d_x11_X11PMBlitLoops_updateBitmask
 209     (JNIEnv *env, jclass xpmbl, jobject srcsd, jobject dstsd, jboolean isICM)
 210 {
 211 #ifndef HEADLESS
 212     SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcsd);
 213     X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, dstsd);
 214     SurfaceDataRasInfo srcInfo;
 215 
 216     int flags;
 217     int screen;
 218     int width;
 219     int height;
 220     jint srcScan, dstScan;
 221     int rowCount;
 222     unsigned char *pDst;
 223     XImage *image;
 224     GC xgc;
 225 
 226     if (srcOps == NULL || xsdo == NULL) {
 227         JNU_ThrowNullPointerException(env, "Null BISD in updateMaskRegion");
 228         return;
 229     }
 230 
 231     AWT_LOCK();
 232 
 233     screen = xsdo->configData->awt_visInfo.screen;
 234     width = xsdo->pmWidth;
 235     height = xsdo->pmHeight;
 236 
 237     if (xsdo->bitmask == 0) {
 238         /* create the bitmask if it is not yet created */
 239         xsdo->bitmask = XCreatePixmap(awt_display,
 240                                       RootWindow(awt_display, screen),
 241                                       width, height, 1);
 242         if (xsdo->bitmask == 0) {
 243             AWT_UNLOCK();
 244             if (!(*env)->ExceptionCheck(env))
 245             {
 246                 JNU_ThrowOutOfMemoryError(env,
 247                                           "Cannot create bitmask for "
 248                                           "offscreen surface");
 249             }
 250             return;
 251         }
 252     }
 253 
 254     /* Create a bitmask image and then blit it to the pixmap. */
 255     image = XCreateImage(awt_display, DefaultVisual(awt_display, screen),
 256                          1, XYBitmap, 0, NULL, width, height, 32, 0);
 257     if (image == NULL) {
 258         AWT_UNLOCK();
 259         if (!(*env)->ExceptionCheck(env))
 260         {
 261              JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
 262         }
 263         return;
 264     }
 265     dstScan = image->bytes_per_line;
 266     image->data = malloc(dstScan * height);
 267     if (image->data == NULL) {
 268         XFree(image);
 269         AWT_UNLOCK();
 270         if (!(*env)->ExceptionCheck(env))
 271         {
 272             JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
 273         }
 274         return;
 275     }
 276     pDst = (unsigned char *)image->data;
 277 
 278     srcInfo.bounds.x1 = 0;
 279     srcInfo.bounds.y1 = 0;
 280     srcInfo.bounds.x2 = width;
 281     srcInfo.bounds.y2 = height;
 282 
 283     flags = (isICM ? (SD_LOCK_LUT | SD_LOCK_READ) : SD_LOCK_READ);
 284     if (srcOps->Lock(env, srcOps, &srcInfo, flags) != SD_SUCCESS) {
 285         XDestroyImage(image);
 286         AWT_UNLOCK();
 287         return;
 288     }
 289     srcOps->GetRasInfo(env, srcOps, &srcInfo);
 290 
 291     rowCount = height;
 292     if (isICM) {
 293         unsigned char *pSrc;
 294         jint *srcLut;
 295 
 296         srcScan = srcInfo.scanStride;
 297         srcLut = srcInfo.lutBase;
 298         pSrc = (unsigned char *)srcInfo.rasBase;
 299 
 300         if (image->bitmap_bit_order == MSBFirst) {
 301             do {
 302                 int x = 0, bx = 0;
 303                 unsigned int pix = 0;
 304                 unsigned int bit = 0x80;
 305                 unsigned char *srcPixel = pSrc;
 306                 do {
 307                     if (bit == 0) {
 308                         pDst[bx++] = (unsigned char)pix;
 309                         pix = 0;
 310                         bit = 0x80;
 311                     }
 312                     pix |= bit & (srcLut[*srcPixel++] >> 31);
 313                     bit >>= 1;
 314                 } while (++x < width);
 315                 pDst[bx] = (unsigned char)pix;
 316                 pDst += dstScan;
 317                 pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
 318             } while (--rowCount > 0);
 319         } else {
 320             do {
 321                 int x = 0, bx = 0;
 322                 unsigned int pix = 0;
 323                 unsigned int bit = 1;
 324                 unsigned char *srcPixel = pSrc;
 325                 do {
 326                     if ((bit >> 8) != 0) {
 327                         pDst[bx++] = (unsigned char) pix;
 328                         pix = 0;
 329                         bit = 1;
 330                     }
 331                     pix |= bit & (srcLut[*srcPixel++] >> 31);
 332                     bit <<= 1;
 333                 } while (++x < width);
 334                 pDst[bx] = (unsigned char) pix;
 335                 pDst += dstScan;
 336                 pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
 337             } while (--rowCount > 0);
 338         }
 339     } else /*DCM with ARGB*/ {
 340         unsigned int *pSrc;
 341 
 342         /* this is a number of pixels in a row, not number of bytes */
 343         srcScan = srcInfo.scanStride;
 344         pSrc = (unsigned int *)srcInfo.rasBase;
 345 
 346         if (image->bitmap_bit_order == MSBFirst) {
 347             do {
 348                 int x = 0, bx = 0;
 349                 unsigned int pix = 0;
 350                 unsigned int bit = 0x80;
 351                 int *srcPixel = (int *) pSrc;
 352                 do {
 353                     if (bit == 0) {
 354                         /* next word */
 355                         pDst[bx++] = (unsigned char)pix;
 356                         pix = 0;
 357                         bit = 0x80;
 358                     }
 359                     if (*srcPixel++ & 0xff000000) {
 360                         /* if src pixel is opaque, set the bit in the bitmap */
 361                         pix |= bit;
 362                     }
 363                     bit >>= 1;
 364                 } while (++x < width);
 365                 /* last pixels in a row */
 366                 pDst[bx] = (unsigned char)pix;
 367 
 368                 pDst += dstScan;
 369                 pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
 370             } while (--rowCount > 0);
 371         } else {
 372             do {
 373                 int x = 0, bx = 0;
 374                 unsigned int pix = 0;
 375                 unsigned int bit = 1;
 376                 int *srcPixel = (int *) pSrc;
 377                 do {
 378                     if ((bit >> 8) != 0) {
 379                         pDst[bx++] = (unsigned char)pix;
 380                         pix = 0;
 381                         bit = 1;
 382                     }
 383                     if (*srcPixel++ & 0xff000000) {
 384                         /* if src pixel is opaque, set the bit in the bitmap */
 385                         pix |= bit;
 386                     }
 387                     bit <<= 1;
 388                 } while (++x < width);
 389                 pDst[bx] = (unsigned char)pix;
 390                 pDst += dstScan;
 391                 pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
 392             } while (--rowCount > 0);
 393         }
 394     }
 395     SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
 396     SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
 397 
 398     xgc = XCreateGC(awt_display, xsdo->bitmask, 0L, NULL);
 399     XSetForeground(awt_display, xgc, 1);
 400     XSetBackground(awt_display, xgc, 0);
 401     XPutImage(awt_display, xsdo->bitmask, xgc,
 402               image, 0, 0, 0, 0, width, height);
 403 
 404     XFreeGC(awt_display, xgc);
 405     XDestroyImage(image);
 406 
 407     AWT_UNLOCK();
 408 #endif /* !HEADLESS */
 409 }