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
32JNIEXPORT void JNICALL
33Java_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
126JNIEXPORT void JNICALL
127Java_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 */
207JNIEXPORT void JNICALL
208Java_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}
410