1 /* 2 * Copyright (c) 2010, 2011, 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 "X11SurfaceData.h" 27 #include <jni.h> 28 #include <math.h> 29 #include "Region.h" 30 #include "fontscalerdefs.h" 31 32 #include <X11/extensions/Xrender.h> 33 34 /* On Solaris 10 updates 8, 9, the render.h file defines these 35 * protocol values but does not define the structs in Xrender.h. 36 * Thus in order to get these always defined on Solaris 10 37 * we will undefine the symbols if we have determined via the 38 * makefiles that Xrender.h is lacking the structs. This will 39 * trigger providing our own definitions as on earlier updates. 40 * We could assume that *all* Solaris 10 update versions will lack the updated 41 * Xrender.h and do this based solely on O/S being any 5.10 version, but this 42 * could still change and we'd be broken again as we'd be re-defining them. 43 */ 44 #ifdef SOLARIS10_NO_XRENDER_STRUCTS 45 #undef X_RenderCreateLinearGradient 46 #undef X_RenderCreateRadialGradient 47 #endif 48 49 #ifndef X_RenderCreateLinearGradient 50 typedef struct _XLinearGradient { 51 XPointFixed p1; 52 XPointFixed p2; 53 } XLinearGradient; 54 #endif 55 56 #ifndef X_RenderCreateRadialGradient 57 typedef struct _XCircle { 58 XFixed x; 59 XFixed y; 60 XFixed radius; 61 } XCircle; 62 63 typedef struct _XRadialGradient { 64 XCircle inner; 65 XCircle outer; 66 } XRadialGradient; 67 #endif 68 69 #ifdef __solaris__ 70 /* Solaris 10 will not have these symbols at runtime */ 71 #include <dlfcn.h> 72 #include <link.h> 73 74 typedef Picture (*XRenderCreateLinearGradientFuncType) 75 (Display *dpy, 76 const XLinearGradient *gradient, 77 const XFixed *stops, 78 const XRenderColor *colors, 79 int nstops); 80 81 typedef Picture (*XRenderCreateRadialGradientFuncType) 82 (Display *dpy, 83 const XRadialGradient *gradient, 84 const XFixed *stops, 85 const XRenderColor *colors, 86 int nstops); 87 88 static 89 XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL; 90 static 91 XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL; 92 #endif 93 94 #define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \ 95 { \ 96 TRANSFORM.matrix[0][0] = M00; \ 97 TRANSFORM.matrix[0][1] = M01; \ 98 TRANSFORM.matrix[0][2] = M02; \ 99 TRANSFORM.matrix[1][0] = M10; \ 100 TRANSFORM.matrix[1][1] = M11; \ 101 TRANSFORM.matrix[1][2] = M12; \ 102 TRANSFORM.matrix[2][0] = 0; \ 103 TRANSFORM.matrix[2][1] = 0; \ 104 TRANSFORM.matrix[2][2] = 1<<16; \ 105 } 106 107 108 static jboolean IsXRenderAvailable() { 109 110 void *xrenderlib; 111 112 int major_opcode, first_event, first_error; 113 114 if (!XQueryExtension(awt_display, "RENDER", 115 &major_opcode, &first_event, &first_error)) { 116 return JNI_FALSE; 117 } 118 119 #ifdef __solaris__ 120 xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY); 121 if (xrenderlib != NULL) { 122 123 XRenderCreateLinearGradientFunc = 124 (XRenderCreateLinearGradientFuncType) 125 dlsym(xrenderlib, "XRenderCreateLinearGradient"); 126 127 XRenderCreateRadialGradientFunc = 128 (XRenderCreateRadialGradientFuncType) 129 dlsym(xrenderlib, "XRenderCreateRadialGradient"); 130 131 if (XRenderCreateLinearGradientFunc == NULL || 132 XRenderCreateRadialGradientFunc == NULL) 133 { 134 dlclose(xrenderlib); 135 return JNI_FALSE; 136 } 137 } 138 #endif 139 return JNI_TRUE; 140 } 141 /* 142 * Class: sun_awt_X11GraphicsEnvironment 143 * Method: initGLX 144 * Signature: ()Z 145 */ 146 JNIEXPORT jboolean JNICALL 147 Java_sun_awt_X11GraphicsEnvironment_initXRender 148 (JNIEnv *env, jclass x11ge) 149 { 150 #ifndef HEADLESS 151 static jboolean xrenderAvailable = JNI_FALSE; 152 static jboolean firstTime = JNI_TRUE; 153 154 if (firstTime) { 155 AWT_LOCK(); 156 xrenderAvailable = IsXRenderAvailable(); 157 AWT_UNLOCK(); 158 firstTime = JNI_FALSE; 159 } 160 return xrenderAvailable; 161 #else 162 return JNI_FALSE; 163 #endif /* !HEADLESS */ 164 } 165 166 167 JNIEXPORT void JNICALL 168 Java_sun_java2d_xr_XRBackendNative_initIDs(JNIEnv *env, jclass cls) { 169 char *maskData; 170 XImage* defaultImg; 171 jfieldID maskImgID; 172 jlong fmt8 = 173 ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardA8)); 174 jlong fmt32 = 175 ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardARGB32)); 176 jfieldID a8ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_A8", "J"); 177 jfieldID argb32ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_ARGB32", "J"); 178 179 (*env)->SetStaticLongField(env, cls, a8ID, fmt8); 180 (*env)->SetStaticLongField(env, cls, argb32ID, fmt32); 181 182 maskData = (char *) malloc(32*32); 183 if (maskData == NULL) { 184 return; 185 } 186 187 defaultImg = XCreateImage(awt_display, NULL, 8, ZPixmap, 0, maskData, 32, 32, 8, 0); 188 defaultImg->data = maskData; //required? 189 maskImgID = (*env)->GetStaticFieldID(env, cls, "MASK_XIMG", "J"); 190 (*env)->SetStaticLongField(env, cls, maskImgID, ptr_to_jlong(defaultImg)); 191 } 192 193 JNIEXPORT void JNICALL 194 Java_sun_java2d_xr_XRBackendNative_freeGC 195 (JNIEnv *env, jobject this, jlong gc) { 196 XFreeGC(awt_display, (GC) jlong_to_ptr(gc)); 197 } 198 199 JNIEXPORT jlong JNICALL 200 Java_sun_java2d_xr_XRBackendNative_createGC 201 (JNIEnv *env, jobject this, jint drawable) { 202 GC xgc = XCreateGC(awt_display, (Drawable) drawable, 0L, NULL); 203 return ptr_to_jlong(xgc); 204 } 205 206 JNIEXPORT jint JNICALL 207 Java_sun_java2d_xr_XRBackendNative_createPixmap(JNIEnv *env, jobject this, 208 jint drawable, jint depth, 209 jint width, jint height) { 210 return (jint) XCreatePixmap(awt_display, (Drawable) drawable, 211 width, height, depth); 212 } 213 214 JNIEXPORT jint JNICALL 215 Java_sun_java2d_xr_XRBackendNative_createPictureNative 216 (JNIEnv *env, jclass cls, jint drawable, jlong formatPtr) { 217 XRenderPictureAttributes pict_attr; 218 return XRenderCreatePicture(awt_display, (Drawable) drawable, 219 (XRenderPictFormat *) jlong_to_ptr(formatPtr), 220 0, &pict_attr); 221 } 222 223 JNIEXPORT void JNICALL 224 Java_sun_java2d_xr_XRBackendNative_freePicture 225 (JNIEnv *env, jobject this, jint picture) { 226 XRenderFreePicture(awt_display, (Picture) picture); 227 } 228 229 JNIEXPORT void JNICALL 230 Java_sun_java2d_xr_XRBackendNative_freePixmap 231 (JNIEnv *env, jobject this, jint pixmap) { 232 XFreePixmap(awt_display, (Pixmap) pixmap); 233 } 234 235 JNIEXPORT void JNICALL 236 Java_sun_java2d_xr_XRBackendNative_setPictureRepeat 237 (JNIEnv *env, jobject this, jint picture, jint repeat) { 238 XRenderPictureAttributes pict_attr; 239 pict_attr.repeat = repeat; 240 XRenderChangePicture (awt_display, (Picture) picture, CPRepeat, &pict_attr); 241 } 242 243 244 JNIEXPORT void JNICALL 245 Java_sun_java2d_xr_XRBackendNative_setGCExposures 246 (JNIEnv *env, jobject this, jlong gc, jboolean exposure) { 247 XSetGraphicsExposures(awt_display, 248 (GC) jlong_to_ptr(gc), exposure ? True : False); //TODO: ???? 249 } 250 251 JNIEXPORT void JNICALL 252 Java_sun_java2d_xr_XRBackendNative_setGCForeground 253 (JNIEnv *env, jobject this, jlong gc, jint pixel) { 254 XSetForeground(awt_display, (GC) jlong_to_ptr(gc), (unsigned long) pixel); 255 } 256 257 258 JNIEXPORT void JNICALL 259 Java_sun_java2d_xr_XRBackendNative_copyArea 260 (JNIEnv *env, jobject this, jint src, jint dst, jlong gc, 261 jint srcx, jint srcy, jint width, jint height, jint dstx, jint dsty) { 262 XCopyArea(awt_display, (Drawable) src, (Drawable) dst, 263 (GC) jlong_to_ptr(gc), srcx, srcy, width, height, dstx, dsty); 264 } 265 266 JNIEXPORT void JNICALL 267 Java_sun_java2d_xr_XRBackendNative_renderComposite 268 (JNIEnv *env, jobject this, jbyte op, jint src, jint mask, jint dst, 269 jint srcX, jint srcY, jint maskX, jint maskY, 270 jint dstX, jint dstY, jint width, jint height) { 271 XRenderComposite (awt_display, op, 272 (Picture)src, (Picture)mask, (Picture)dst, 273 srcX, srcY, maskX, maskY, dstX, dstY, width, height); 274 } 275 276 JNIEXPORT void JNICALL 277 Java_sun_java2d_xr_XRBackendNative_renderRectangle 278 (JNIEnv *env, jobject this, jint dst, jbyte op, 279 jshort red, jshort green, jshort blue, jshort alpha, 280 jint x, jint y, jint width, jint height) { 281 XRenderColor color; 282 color.alpha = alpha; 283 color.red = red; 284 color.green = green; 285 color.blue = blue; 286 XRenderFillRectangle(awt_display, op, (Picture) dst, &color, 287 x, y, width, height); 288 } 289 290 JNIEXPORT void JNICALL 291 Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative 292 (JNIEnv *env, jclass xsd, jint dst, jbyte op, 293 jshort red, jshort green, jshort blue, jshort alpha, 294 jintArray rectArray, jint rectCnt) { 295 int i; 296 jint* rects; 297 XRectangle *xRects; 298 XRectangle sRects[256]; 299 300 XRenderColor color; 301 color.alpha = alpha; 302 color.red = red; 303 color.green = green; 304 color.blue = blue; 305 306 if (rectCnt <= 256) { 307 xRects = &sRects[0]; 308 } else { 309 xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt); 310 if (xRects == NULL) { 311 return; 312 } 313 } 314 315 if ((rects = (jint *) 316 (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) { 317 if (xRects != &sRects[0]) { 318 free(xRects); 319 } 320 return; 321 } 322 323 for (i=0; i < rectCnt; i++) { 324 xRects[i].x = rects[i*4 + 0]; 325 xRects[i].y = rects[i*4 + 1]; 326 xRects[i].width = rects[i*4 + 2]; 327 xRects[i].height = rects[i*4 + 3]; 328 } 329 330 XRenderFillRectangles(awt_display, op, 331 (Picture) dst, &color, xRects, rectCnt); 332 333 (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT); 334 if (xRects != &sRects[0]) { 335 free(xRects); 336 } 337 } 338 339 JNIEXPORT void JNICALL 340 Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative 341 (JNIEnv *env, jclass xsd, jint pic, 342 jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) { 343 344 XTransform tr; 345 BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12); 346 XRenderSetPictureTransform (awt_display, (Picture) pic, &tr); 347 } 348 349 JNIEXPORT jint JNICALL 350 Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative 351 (JNIEnv *env, jclass xsd, jfloatArray fractionsArray, 352 jshortArray pixelsArray, jint x1, jint y1, jint x2, jint y2, 353 jint numStops, jint repeat, 354 jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) { 355 jint i; 356 jshort* pixels; 357 jfloat* fractions; 358 XTransform tr; 359 XRenderPictureAttributes pict_attr; 360 Picture gradient = 0; 361 XRenderColor *colors; 362 XFixed *stops; 363 XLinearGradient grad; 364 365 if ((pixels = (jshort *) 366 (*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) { 367 return -1; 368 } 369 if ((fractions = (jfloat *) 370 (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) { 371 (*env)->ReleasePrimitiveArrayCritical(env, 372 pixelsArray, pixels, JNI_ABORT); 373 return -1; 374 } 375 376 grad.p1.x = x1; 377 grad.p1.y = y1; 378 grad.p2.x = x2; 379 grad.p2.y = y2; 380 381 /*TODO optimized & malloc check*/ 382 colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor)); 383 stops = (XFixed *) malloc(numStops * sizeof(XFixed)); 384 385 for (i=0; i < numStops; i++) { 386 stops[i] = XDoubleToFixed(fractions[i]); 387 colors[i].alpha = pixels[i*4 + 0]; 388 colors[i].red = pixels[i*4 + 1]; 389 colors[i].green = pixels[i*4 + 2]; 390 colors[i].blue = pixels[i*4 + 3]; 391 } 392 #ifdef __solaris__ 393 if (XRenderCreateLinearGradientFunc!=NULL) { 394 gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops); 395 } 396 #else 397 gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops); 398 #endif 399 free(colors); 400 free(stops); 401 402 (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT); 403 (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT); 404 405 if (gradient != 0) { 406 BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12); 407 XRenderSetPictureTransform (awt_display, gradient, &tr); 408 pict_attr.repeat = repeat; 409 XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr); 410 } 411 412 return (jint) gradient; 413 } 414 415 416 JNIEXPORT jint JNICALL 417 Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative 418 (JNIEnv *env, jclass xsd, jfloatArray fractionsArray, 419 jshortArray pixelsArray, jint numStops, 420 jint innerRadius, jint outerRadius, jint repeat, 421 jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) { 422 jint i; 423 jshort* pixels; 424 jfloat* fractions; 425 XTransform tr; 426 XRenderPictureAttributes pict_attr; 427 Picture gradient = 0; 428 XRenderColor *colors; 429 XFixed *stops; 430 XRadialGradient grad; 431 432 433 if ((pixels = 434 (jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) { 435 return -1; 436 } 437 if ((fractions = (jfloat *) 438 (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) { 439 (*env)->ReleasePrimitiveArrayCritical(env, 440 pixelsArray, pixels, JNI_ABORT); 441 return -1; //TODO release pixels first 442 } 443 444 grad.inner.x = 0; 445 grad.inner.y = 0; 446 grad.inner.radius = innerRadius; 447 grad.outer.x = 0; 448 grad.outer.y = 0; 449 grad.outer.radius = outerRadius; 450 451 /*TODO optimized & malloc check*/ 452 colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor)); 453 stops = (XFixed *) malloc(numStops * sizeof(XFixed)); 454 455 for (i=0; i < numStops; i++) { 456 stops[i] = XDoubleToFixed(fractions[i]); 457 colors[i].alpha = pixels[i*4 + 0]; 458 colors[i].red = pixels[i*4 + 1]; 459 colors[i].green = pixels[i*4 + 2]; 460 colors[i].blue = pixels[i*4 + 3]; 461 } 462 #ifdef __solaris__ 463 if (XRenderCreateRadialGradientFunc != NULL) { 464 gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops); 465 } 466 #else 467 gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops); 468 #endif 469 free(colors); 470 free(stops); 471 472 (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT); 473 (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT); 474 475 476 if (gradient != 0) { 477 BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12); 478 XRenderSetPictureTransform (awt_display, gradient, &tr); 479 pict_attr.repeat = repeat; 480 XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr); 481 } 482 483 return (jint) gradient; 484 } 485 486 JNIEXPORT void JNICALL 487 Java_sun_java2d_xr_XRBackendNative_setFilter 488 (JNIEnv *env, jobject this, jint picture, jint filter) { 489 490 char * filterName = "fast"; 491 492 switch(filter) { 493 case 0: 494 filterName = "fast"; 495 break; 496 497 case 1: 498 filterName = "good"; 499 break; 500 501 case 2: 502 filterName = "best"; 503 break; 504 } 505 506 XRenderSetPictureFilter(awt_display, (Picture) picture, filterName, NULL, 0); 507 } 508 509 JNIEXPORT void JNICALL 510 Java_sun_java2d_xr_XRBackendNative_XRSetClipNative 511 (JNIEnv *env, jclass xsd, jlong dst, 512 jint x1, jint y1, jint x2, jint y2, 513 jobject complexclip, jboolean isGC) 514 { 515 int numrects; 516 XRectangle rects[256]; 517 XRectangle *pRect = rects; 518 519 numrects = RegionToYXBandedRectangles(env, 520 x1, y1, x2, y2, complexclip, 521 &pRect, 256); 522 523 if (isGC == JNI_TRUE) { 524 if (dst != (jlong) 0) { 525 XSetClipRectangles(awt_display, (GC) jlong_to_ptr(dst), 0, 0, pRect, numrects, YXBanded); 526 } 527 } else { 528 XRenderSetPictureClipRectangles (awt_display, (Picture) dst, 0, 0, pRect, numrects); 529 } 530 531 if (pRect != rects) { 532 free(pRect); 533 } 534 } 535 536 JNIEXPORT void JNICALL 537 Java_sun_java2d_xr_XRBackendNative_putMaskNative 538 (JNIEnv *env, jclass cls, jint drawable, jlong gc, jbyteArray imageData, 539 jint sx, jint sy, jint dx, jint dy, jint width, jint height, 540 jint maskOff, jint maskScan, jfloat ea, jlong imgPtr) { 541 542 int line, pix; 543 char *mask; 544 char *defaultData; 545 XImage *defaultImg, *img; 546 jboolean imageFits; 547 548 if ((mask = (char *) 549 (*env)->GetPrimitiveArrayCritical(env, imageData, NULL)) == NULL) { 550 return; 551 } 552 553 defaultImg = (XImage *) jlong_to_ptr(imgPtr); 554 555 if (ea != 1.0f) { 556 for (line=0; line < height; line++) { 557 for (pix=0; pix < width; pix++) { 558 int index = maskScan*line + pix + maskOff; 559 mask[index] = (((unsigned char) mask[index])*ea); 560 } 561 } 562 } 563 564 /* 565 * 1. If existing XImage and supplied buffer match, only adjust the data pointer 566 * 2. If existing XImage is large enough to hold the data but does not match in 567 * scan the data is copied to fit the XImage. 568 * 3. If data is larger than the existing XImage a new temporary XImage is 569 * allocated. 570 * The default XImage is optimized for the AA tiles, which are currently 32x32. 571 */ 572 defaultData = defaultImg->data; 573 img = defaultImg; 574 imageFits = defaultImg->width >= width && defaultImg->height >= height; 575 576 if (imageFits && 577 maskOff == defaultImg->xoffset && maskScan == defaultImg->bytes_per_line) { 578 defaultImg->data = mask; 579 } else { 580 if (imageFits) { 581 for (line=0; line < height; line++) { 582 for (pix=0; pix < width; pix++) { 583 img->data[line*img->bytes_per_line + pix] = 584 (unsigned char) (mask[maskScan*line + pix + maskOff]); 585 } 586 } 587 } else { 588 img = XCreateImage(awt_display, NULL, 8, ZPixmap, 589 maskOff, mask, maskScan, height, 8, 0); 590 } 591 } 592 593 XPutImage(awt_display, (Pixmap) drawable, (GC) jlong_to_ptr(gc), 594 img, 0, 0, 0, 0, width, height); 595 (*env)->ReleasePrimitiveArrayCritical(env, imageData, mask, JNI_ABORT); 596 597 if (img != defaultImg) { 598 img->data = NULL; 599 XDestroyImage(img); 600 } 601 defaultImg->data = defaultData; 602 } 603 604 JNIEXPORT void JNICALL 605 Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative 606 (JNIEnv *env, jclass cls, jint glyphSet, 607 jlongArray glyphInfoPtrsArray, jint glyphCnt, 608 jbyteArray pixelDataArray, int pixelDataLength) { 609 jlong *glyphInfoPtrs; 610 unsigned char *pixelData; 611 int i; 612 613 XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt); 614 Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt); 615 616 if (xginfo == NULL || gid == NULL) { 617 if (xginfo != NULL) { 618 free(xginfo); 619 } 620 if (gid != NULL) { 621 free(gid); 622 } 623 return; 624 } 625 626 if ((glyphInfoPtrs = (jlong *)(*env)-> 627 GetPrimitiveArrayCritical(env, glyphInfoPtrsArray, NULL)) == NULL) 628 { 629 free(xginfo); 630 free(gid); 631 return; 632 } 633 634 if ((pixelData = (unsigned char *) 635 (*env)->GetPrimitiveArrayCritical(env, pixelDataArray, NULL)) == NULL) 636 { 637 (*env)->ReleasePrimitiveArrayCritical(env, 638 glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT); 639 free(xginfo); 640 free(gid); 641 return; 642 } 643 644 for (i=0; i < glyphCnt; i++) { 645 GlyphInfo *jginfo = (GlyphInfo *) jlong_to_ptr(glyphInfoPtrs[i]); 646 647 gid[i] = (Glyph) (0xffffffff & ((unsigned int) jginfo->cellInfo)); 648 xginfo[i].x = (-jginfo->topLeftX); 649 xginfo[i].y = (-jginfo->topLeftY); 650 xginfo[i].width = jginfo->width; 651 xginfo[i].height = jginfo->height; 652 xginfo[i].xOff = round(jginfo->advanceX); 653 xginfo[i].yOff = round(jginfo->advanceY); 654 } 655 656 XRenderAddGlyphs(awt_display, glyphSet, &gid[0], &xginfo[0], glyphCnt, 657 (const char*)pixelData, pixelDataLength); 658 659 (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT); 660 (*env)->ReleasePrimitiveArrayCritical(env, pixelDataArray, pixelData, JNI_ABORT); 661 662 free(xginfo); 663 free(gid); 664 } 665 666 JNIEXPORT void JNICALL 667 Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative 668 (JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) { 669 jint *gids; 670 int i; 671 672 if ((gids = (jint *) (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL)) == NULL) { 673 return; 674 } 675 676 XRenderFreeGlyphs (awt_display, (GlyphSet) glyphSet, (Glyph *) gids, glyphCnt); 677 678 (*env)->ReleasePrimitiveArrayCritical(env, gidArray, gids, JNI_ABORT); 679 } 680 681 JNIEXPORT jint JNICALL 682 Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative 683 (JNIEnv *env, jclass cls, jlong format) { 684 return XRenderCreateGlyphSet(awt_display, (XRenderPictFormat *) jlong_to_ptr(format)); 685 } 686 687 JNIEXPORT void JNICALL 688 Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative 689 (JNIEnv *env, jclass cls, jint op, jint src, jint dst, jlong maskFmt, 690 jintArray eltArray, jintArray glyphIDArray, jint eltCnt, jint glyphCnt) { 691 jint i; 692 jint *ids; 693 jint *elts; 694 XGlyphElt32 *xelts; 695 Glyph *xids; 696 XGlyphElt32 selts[24]; 697 Glyph sids[256]; 698 int charCnt = 0; 699 700 if (eltCnt <= 24) { 701 xelts = &selts[0]; 702 }else { 703 xelts = (XGlyphElt32 *) malloc(sizeof(XGlyphElt32) * eltCnt); 704 if (xelts == NULL) { 705 return; 706 } 707 } 708 709 if (glyphCnt <= 256) { 710 xids = &sids[0]; 711 } else { 712 xids = (Glyph *) malloc(sizeof(Glyph) * glyphCnt); 713 if (xids == NULL) { 714 if (xelts != &selts[0]) { 715 free(xelts); 716 } 717 return; 718 } 719 } 720 721 if ((ids = (jint *) 722 (*env)->GetPrimitiveArrayCritical(env, glyphIDArray, NULL)) == NULL) { 723 if (xelts != &selts[0]) { 724 free(xelts); 725 } 726 if (xids != &sids[0]) { 727 free(xids); 728 } 729 return; 730 } 731 if ((elts = (jint *) 732 (*env)->GetPrimitiveArrayCritical(env, eltArray, NULL)) == NULL) { 733 (*env)->ReleasePrimitiveArrayCritical(env, 734 glyphIDArray, ids, JNI_ABORT); 735 if (xelts != &selts[0]) { 736 free(xelts); 737 } 738 if (xids != &sids[0]) { 739 free(xids); 740 } 741 return; 742 } 743 744 for (i=0; i < glyphCnt; i++) { 745 xids[i] = (Glyph) ids[i]; 746 } 747 748 for (i=0; i < eltCnt; i++) { 749 xelts[i].nchars = elts[i*4 + 0]; 750 xelts[i].xOff = elts[i*4 + 1]; 751 xelts[i].yOff = elts[i*4 + 2]; 752 xelts[i].glyphset = (GlyphSet) elts[i*4 + 3]; 753 xelts[i].chars = (unsigned int *) &xids[charCnt]; 754 755 charCnt += xelts[i].nchars; 756 } 757 758 XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst, 759 (XRenderPictFormat *) jlong_to_ptr(maskFmt), 760 0, 0, 0, 0, xelts, eltCnt); 761 762 (*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT); 763 (*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT); 764 765 if (xelts != &selts[0]) { 766 free(xelts); 767 } 768 769 if (xids != &sids[0]) { 770 free(xids); 771 } 772 } 773 774 JNIEXPORT void JNICALL 775 Java_sun_java2d_xr_XRBackendNative_setGCMode 776 (JNIEnv *env, jobject this, jlong gc, jboolean copy) { 777 GC xgc = (GC) jlong_to_ptr(gc); 778 779 if (copy == JNI_TRUE) { 780 XSetFunction(awt_display, xgc, GXcopy); 781 } else { 782 XSetFunction(awt_display, xgc, GXxor); 783 } 784 } 785 786 JNIEXPORT void JNICALL 787 Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative 788 (JNIEnv *env, jclass xsd, jint dst, jlong gc, 789 jintArray rectArray, jint rectCnt) { 790 int i; 791 jint* rects; 792 XRectangle *xRects; 793 XRectangle sRects[256]; 794 795 if (rectCnt <= 256) { 796 xRects = &sRects[0]; 797 } else { 798 xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt); 799 if (xRects == NULL) { 800 return; 801 } 802 } 803 804 if ((rects = (jint*) 805 (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) { 806 if (xRects != &sRects[0]) { 807 free(xRects); 808 } 809 return; 810 } 811 812 for (i=0; i < rectCnt; i++) { 813 xRects[i].x = rects[i*4 + 0]; 814 xRects[i].y = rects[i*4 + 1]; 815 xRects[i].width = rects[i*4 + 2]; 816 xRects[i].height = rects[i*4 + 3]; 817 } 818 819 XFillRectangles(awt_display, (Drawable) dst, (GC) jlong_to_ptr(gc), xRects, rectCnt); 820 821 (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT); 822 if (xRects != &sRects[0]) { 823 free(xRects); 824 } 825 } 826 827 JNIEXPORT void JNICALL 828 Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative 829 (JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt, 830 jint dst, jint srcX, jint srcY, jintArray trapArray) { 831 jint *traps; 832 833 if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) { 834 return; 835 } 836 837 XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst, 838 (XRenderPictFormat *) jlong_to_ptr(maskFmt), 839 srcX, srcY, (XTrapezoid *) (traps+5), traps[0]); 840 841 (*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT); 842 }