blob: 417678272d06a78c60dad66ca28255c86233aa90 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 JNU_ThrowOutOfMemoryError(env,
245 "Cannot create bitmask for "
246 "offscreen surface");
247 return;
248 }
249 }
250
251 /* Create a bitmask image and then blit it to the pixmap. */
252 image = XCreateImage(awt_display, DefaultVisual(awt_display, screen),
253 1, XYBitmap, 0, NULL, width, height, 32, 0);
254 if (image == NULL) {
255 AWT_UNLOCK();
256 JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
257 return;
258 }
259 dstScan = image->bytes_per_line;
260 image->data = malloc(dstScan * height);
261 if (image->data == NULL) {
262 XFree(image);
263 AWT_UNLOCK();
264 JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask");
265 return;
266 }
267 pDst = (unsigned char *)image->data;
268
269 srcInfo.bounds.x1 = 0;
270 srcInfo.bounds.y1 = 0;
271 srcInfo.bounds.x2 = width;
272 srcInfo.bounds.y2 = height;
273
274 flags = (isICM ? (SD_LOCK_LUT | SD_LOCK_READ) : SD_LOCK_READ);
275 if (srcOps->Lock(env, srcOps, &srcInfo, flags) != SD_SUCCESS) {
276 XDestroyImage(image);
277 AWT_UNLOCK();
278 return;
279 }
280 srcOps->GetRasInfo(env, srcOps, &srcInfo);
281
282 rowCount = height;
283 if (isICM) {
284 unsigned char *pSrc;
285 jint *srcLut;
286
287 srcScan = srcInfo.scanStride;
288 srcLut = srcInfo.lutBase;
289 pSrc = (unsigned char *)srcInfo.rasBase;
290
291 if (image->bitmap_bit_order == MSBFirst) {
292 do {
293 int x = 0, bx = 0;
294 unsigned int pix = 0;
295 unsigned int bit = 0x80;
296 unsigned char *srcPixel = pSrc;
297 do {
298 if (bit == 0) {
299 pDst[bx++] = (unsigned char)pix;
300 pix = 0;
301 bit = 0x80;
302 }
303 pix |= bit & (srcLut[*srcPixel++] >> 31);
304 bit >>= 1;
305 } while (++x < width);
306 pDst[bx] = (unsigned char)pix;
307 pDst += dstScan;
308 pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
309 } while (--rowCount > 0);
310 } else {
311 do {
312 int x = 0, bx = 0;
313 unsigned int pix = 0;
314 unsigned int bit = 1;
315 unsigned char *srcPixel = pSrc;
316 do {
317 if ((bit >> 8) != 0) {
318 pDst[bx++] = (unsigned char) pix;
319 pix = 0;
320 bit = 1;
321 }
322 pix |= bit & (srcLut[*srcPixel++] >> 31);
323 bit <<= 1;
324 } while (++x < width);
325 pDst[bx] = (unsigned char) pix;
326 pDst += dstScan;
327 pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan);
328 } while (--rowCount > 0);
329 }
330 } else /*DCM with ARGB*/ {
331 unsigned int *pSrc;
332
333 /* this is a number of pixels in a row, not number of bytes */
334 srcScan = srcInfo.scanStride;
335 pSrc = (unsigned int *)srcInfo.rasBase;
336
337 if (image->bitmap_bit_order == MSBFirst) {
338 do {
339 int x = 0, bx = 0;
340 unsigned int pix = 0;
341 unsigned int bit = 0x80;
342 int *srcPixel = (int *) pSrc;
343 do {
344 if (bit == 0) {
345 /* next word */
346 pDst[bx++] = (unsigned char)pix;
347 pix = 0;
348 bit = 0x80;
349 }
350 if (*srcPixel++ & 0xff000000) {
351 /* if src pixel is opaque, set the bit in the bitmap */
352 pix |= bit;
353 }
354 bit >>= 1;
355 } while (++x < width);
356 /* last pixels in a row */
357 pDst[bx] = (unsigned char)pix;
358
359 pDst += dstScan;
360 pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
361 } while (--rowCount > 0);
362 } else {
363 do {
364 int x = 0, bx = 0;
365 unsigned int pix = 0;
366 unsigned int bit = 1;
367 int *srcPixel = (int *) pSrc;
368 do {
369 if ((bit >> 8) != 0) {
370 pDst[bx++] = (unsigned char)pix;
371 pix = 0;
372 bit = 1;
373 }
374 if (*srcPixel++ & 0xff000000) {
375 /* if src pixel is opaque, set the bit in the bitmap */
376 pix |= bit;
377 }
378 bit <<= 1;
379 } while (++x < width);
380 pDst[bx] = (unsigned char)pix;
381 pDst += dstScan;
382 pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan);
383 } while (--rowCount > 0);
384 }
385 }
386 SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
387 SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
388
389 xgc = XCreateGC(awt_display, xsdo->bitmask, 0L, NULL);
390 XSetForeground(awt_display, xgc, 1);
391 XSetBackground(awt_display, xgc, 0);
392 XPutImage(awt_display, xsdo->bitmask, xgc,
393 image, 0, 0, 0, 0, width, height);
394
395 XFreeGC(awt_display, xgc);
396 XDestroyImage(image);
397
398 AWT_UNLOCK();
399#endif /* !HEADLESS */
400}