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 #include <dlfcn.h> 70 71 #ifdef __solaris__ 72 /* Solaris 10 will not have these symbols at runtime */ 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 /* The xrender pipleine requires libXrender.so version 0.9.3 or later. */ 108 #define REQUIRED_XRENDER_VER1 0 109 #define REQUIRED_XRENDER_VER2 9 110 #define REQUIRED_XRENDER_VER3 3 111 112 #define PKGINFO_LINE_LEN_MAX 256 113 #define PKGINFO_LINE_CNT_MAX 50 114 115 static jboolean IsXRenderAvailable(jboolean verbose) { 116 117 void *xrenderlib; 118 119 int major_opcode, first_event, first_error; 120 jboolean available = JNI_TRUE; 121 122 if (!XQueryExtension(awt_display, "RENDER", 123 &major_opcode, &first_event, &first_error)) { 124 return JNI_FALSE; 125 } 126 127 #ifdef __solaris__ 128 xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY); 129 if (xrenderlib != NULL) { 130 131 XRenderCreateLinearGradientFunc = 132 (XRenderCreateLinearGradientFuncType) 133 dlsym(xrenderlib, "XRenderCreateLinearGradient"); 134 135 XRenderCreateRadialGradientFunc = 136 (XRenderCreateRadialGradientFuncType) 137 dlsym(xrenderlib, "XRenderCreateRadialGradient"); 138 139 if (XRenderCreateLinearGradientFunc == NULL || 140 XRenderCreateRadialGradientFunc == NULL) 141 { 142 available = JNI_FALSE; 143 } 144 dlclose(xrenderlib); 145 } else { 146 available = JNI_FALSE; 147 } 148 #else 149 Dl_info info; 150 jboolean versionInfoIsFound = JNI_FALSE; 151 152 memset(&info, 0, sizeof(Dl_info)); 153 if (dladdr(&XRenderChangePicture, &info) && info.dli_fname != NULL) { 154 char pkgInfoPath[FILENAME_MAX]; 155 char *pkgFileName = "/pkgconfig/xrender.pc"; 156 size_t pkgFileNameLen = strlen(pkgFileName); 157 size_t pos, len = strlen(info.dli_fname); 158 159 pos = len; 160 while (pos > 0 && info.dli_fname[pos] != '/') { 161 pos -= 1; 162 } 163 164 if (pos > 0 && pos < (FILENAME_MAX - pkgFileNameLen - 1)) { 165 struct stat stat_info; 166 167 // compose absolute filename to package config 168 strncpy(pkgInfoPath, info.dli_fname, pos); 169 170 strcpy(pkgInfoPath + pos, pkgFileName); 171 pkgInfoPath[pos + pkgFileNameLen] = '\0'; 172 173 // check whether the config file exist and is a regular file 174 if ((stat(pkgInfoPath, &stat_info)== 0) && 175 S_ISREG(stat_info.st_mode)) 176 { 177 FILE *fp = fopen(pkgInfoPath, "r"); 178 if (fp != NULL) { 179 char line[PKGINFO_LINE_LEN_MAX]; 180 int lineCount = PKGINFO_LINE_CNT_MAX; 181 char *versionPrefix = "Version: "; 182 size_t versionPrefixLen = strlen(versionPrefix); 183 184 // look for version 185 while(fgets(line,sizeof(line),fp) != NULL && --lineCount > 0) { 186 size_t lineLen = strlen(line); 187 188 if (lineLen > versionPrefixLen && 189 strncmp(versionPrefix, line, versionPrefixLen) == 0) 190 { 191 int v1 = 0, v2 = 0, v3 = 0; 192 int numNeeded = 3,numProcessed; 193 char* version = line + versionPrefixLen; 194 numProcessed = sscanf(version, "%d.%d.%d", &v1, &v2, &v3); 195 196 if (numProcessed == numNeeded) { 197 // we successfuly read the library version 198 versionInfoIsFound = JNI_TRUE; 199 200 if (REQUIRED_XRENDER_VER1 == v1 && 201 ((REQUIRED_XRENDER_VER2 > v2) || 202 ((REQUIRED_XRENDER_VER2 == v2) && (REQUIRED_XRENDER_VER3 > v3)))) 203 { 204 available = JNI_FALSE; 205 206 if (verbose) { 207 printf("INFO: the version %d.%d.%d of libXrender.so is " 208 "not supported.\n\tSee release notes for more details.\n", 209 v1, v2, v3); 210 fflush(stdout); 211 } 212 } else { 213 if (verbose) { 214 printf("INFO: The version of libXrender.so " 215 "is detected as %d.%d%d\n", v1, v2, v3); 216 fflush(stdout); 217 } 218 } 219 } 220 break; 221 } 222 } 223 fclose(fp); 224 } 225 } 226 } 227 } 228 if (verbose && !versionInfoIsFound) { 229 printf("WARNING: The version of libXrender.so cannot be detected.\n," 230 "The pipe line will be enabled, but note that versions less than 0.9.3\n" 231 "may cause hangs and crashes\n" 232 "\tSee the release notes for more details.\n"); 233 fflush(stdout); 234 } 235 #endif 236 237 return available; 238 } 239 /* 240 * Class: sun_awt_X11GraphicsEnvironment 241 * Method: initGLX 242 * Signature: ()Z 243 */ 244 JNIEXPORT jboolean JNICALL 245 Java_sun_awt_X11GraphicsEnvironment_initXRender 246 (JNIEnv *env, jclass x11ge, jboolean verbose) 247 { 248 #ifndef HEADLESS 249 static jboolean xrenderAvailable = JNI_FALSE; 250 static jboolean firstTime = JNI_TRUE; 251 252 if (firstTime) { 253 AWT_LOCK(); 254 xrenderAvailable = IsXRenderAvailable(verbose); 255 AWT_UNLOCK(); 256 firstTime = JNI_FALSE; 257 } 258 return xrenderAvailable; 259 #else 260 return JNI_FALSE; 261 #endif /* !HEADLESS */ 262 } 263 264 265 JNIEXPORT void JNICALL 266 Java_sun_java2d_xr_XRBackendNative_initIDs(JNIEnv *env, jclass cls) { 267 char *maskData; 268 XImage* defaultImg; 269 jfieldID maskImgID; 270 jlong fmt8 = 271 ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardA8)); 272 jlong fmt32 = 273 ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardARGB32)); 274 jfieldID a8ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_A8", "J"); 275 jfieldID argb32ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_ARGB32", "J"); 276 277 (*env)->SetStaticLongField(env, cls, a8ID, fmt8); 278 (*env)->SetStaticLongField(env, cls, argb32ID, fmt32); 279 280 maskData = (char *) malloc(32*32); 281 if (maskData == NULL) { 282 return; 283 } 284 285 defaultImg = XCreateImage(awt_display, NULL, 8, ZPixmap, 0, maskData, 32, 32, 8, 0); 286 defaultImg->data = maskData; //required? 287 maskImgID = (*env)->GetStaticFieldID(env, cls, "MASK_XIMG", "J"); 288 (*env)->SetStaticLongField(env, cls, maskImgID, ptr_to_jlong(defaultImg)); 289 } 290 291 JNIEXPORT void JNICALL 292 Java_sun_java2d_xr_XRBackendNative_freeGC 293 (JNIEnv *env, jobject this, jlong gc) { 294 XFreeGC(awt_display, (GC) jlong_to_ptr(gc)); 295 } 296 297 JNIEXPORT jlong JNICALL 298 Java_sun_java2d_xr_XRBackendNative_createGC 299 (JNIEnv *env, jobject this, jint drawable) { 300 GC xgc = XCreateGC(awt_display, (Drawable) drawable, 0L, NULL); 301 return ptr_to_jlong(xgc); 302 } 303 304 JNIEXPORT jint JNICALL 305 Java_sun_java2d_xr_XRBackendNative_createPixmap(JNIEnv *env, jobject this, 306 jint drawable, jint depth, 307 jint width, jint height) { 308 return (jint) XCreatePixmap(awt_display, (Drawable) drawable, 309 width, height, depth); 310 } 311 312 JNIEXPORT jint JNICALL 313 Java_sun_java2d_xr_XRBackendNative_createPictureNative 314 (JNIEnv *env, jclass cls, jint drawable, jlong formatPtr) { 315 XRenderPictureAttributes pict_attr; 316 return XRenderCreatePicture(awt_display, (Drawable) drawable, 317 (XRenderPictFormat *) jlong_to_ptr(formatPtr), 318 0, &pict_attr); 319 } 320 321 JNIEXPORT void JNICALL 322 Java_sun_java2d_xr_XRBackendNative_freePicture 323 (JNIEnv *env, jobject this, jint picture) { 324 XRenderFreePicture(awt_display, (Picture) picture); 325 } 326 327 JNIEXPORT void JNICALL 328 Java_sun_java2d_xr_XRBackendNative_freePixmap 329 (JNIEnv *env, jobject this, jint pixmap) { 330 XFreePixmap(awt_display, (Pixmap) pixmap); 331 } 332 333 JNIEXPORT void JNICALL 334 Java_sun_java2d_xr_XRBackendNative_setPictureRepeat 335 (JNIEnv *env, jobject this, jint picture, jint repeat) { 336 XRenderPictureAttributes pict_attr; 337 pict_attr.repeat = repeat; 338 XRenderChangePicture (awt_display, (Picture) picture, CPRepeat, &pict_attr); 339 } 340 341 342 JNIEXPORT void JNICALL 343 Java_sun_java2d_xr_XRBackendNative_setGCExposures 344 (JNIEnv *env, jobject this, jlong gc, jboolean exposure) { 345 XSetGraphicsExposures(awt_display, 346 (GC) jlong_to_ptr(gc), exposure ? True : False); //TODO: ???? 347 } 348 349 JNIEXPORT void JNICALL 350 Java_sun_java2d_xr_XRBackendNative_setGCForeground 351 (JNIEnv *env, jobject this, jlong gc, jint pixel) { 352 XSetForeground(awt_display, (GC) jlong_to_ptr(gc), (unsigned long) pixel); 353 } 354 355 356 JNIEXPORT void JNICALL 357 Java_sun_java2d_xr_XRBackendNative_copyArea 358 (JNIEnv *env, jobject this, jint src, jint dst, jlong gc, 359 jint srcx, jint srcy, jint width, jint height, jint dstx, jint dsty) { 360 XCopyArea(awt_display, (Drawable) src, (Drawable) dst, 361 (GC) jlong_to_ptr(gc), srcx, srcy, width, height, dstx, dsty); 362 } 363 364 JNIEXPORT void JNICALL 365 Java_sun_java2d_xr_XRBackendNative_renderComposite 366 (JNIEnv *env, jobject this, jbyte op, jint src, jint mask, jint dst, 367 jint srcX, jint srcY, jint maskX, jint maskY, 368 jint dstX, jint dstY, jint width, jint height) { 369 XRenderComposite (awt_display, op, 370 (Picture)src, (Picture)mask, (Picture)dst, 371 srcX, srcY, maskX, maskY, dstX, dstY, width, height); 372 } 373 374 JNIEXPORT void JNICALL 375 Java_sun_java2d_xr_XRBackendNative_renderRectangle 376 (JNIEnv *env, jobject this, jint dst, jbyte op, 377 jshort red, jshort green, jshort blue, jshort alpha, 378 jint x, jint y, jint width, jint height) { 379 XRenderColor color; 380 color.alpha = alpha; 381 color.red = red; 382 color.green = green; 383 color.blue = blue; 384 XRenderFillRectangle(awt_display, op, (Picture) dst, &color, 385 x, y, width, height); 386 } 387 388 JNIEXPORT void JNICALL 389 Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative 390 (JNIEnv *env, jclass xsd, jint dst, jbyte op, 391 jshort red, jshort green, jshort blue, jshort alpha, 392 jintArray rectArray, jint rectCnt) { 393 int i; 394 jint* rects; 395 XRectangle *xRects; 396 XRectangle sRects[256]; 397 398 XRenderColor color; 399 color.alpha = alpha; 400 color.red = red; 401 color.green = green; 402 color.blue = blue; 403 404 if (rectCnt <= 256) { 405 xRects = &sRects[0]; 406 } else { 407 xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt); 408 if (xRects == NULL) { 409 return; 410 } 411 } 412 413 if ((rects = (jint *) 414 (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) { 415 if (xRects != &sRects[0]) { 416 free(xRects); 417 } 418 return; 419 } 420 421 for (i=0; i < rectCnt; i++) { 422 xRects[i].x = rects[i*4 + 0]; 423 xRects[i].y = rects[i*4 + 1]; 424 xRects[i].width = rects[i*4 + 2]; 425 xRects[i].height = rects[i*4 + 3]; 426 } 427 428 XRenderFillRectangles(awt_display, op, 429 (Picture) dst, &color, xRects, rectCnt); 430 431 (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT); 432 if (xRects != &sRects[0]) { 433 free(xRects); 434 } 435 } 436 437 JNIEXPORT void JNICALL 438 Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative 439 (JNIEnv *env, jclass xsd, jint pic, 440 jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) { 441 442 XTransform tr; 443 BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12); 444 XRenderSetPictureTransform (awt_display, (Picture) pic, &tr); 445 } 446 447 JNIEXPORT jint JNICALL 448 Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative 449 (JNIEnv *env, jclass xsd, jfloatArray fractionsArray, 450 jshortArray pixelsArray, jint x1, jint y1, jint x2, jint y2, 451 jint numStops, jint repeat, 452 jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) { 453 jint i; 454 jshort* pixels; 455 jfloat* fractions; 456 XTransform tr; 457 XRenderPictureAttributes pict_attr; 458 Picture gradient = 0; 459 XRenderColor *colors; 460 XFixed *stops; 461 XLinearGradient grad; 462 463 if ((pixels = (jshort *) 464 (*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) { 465 return -1; 466 } 467 if ((fractions = (jfloat *) 468 (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) { 469 (*env)->ReleasePrimitiveArrayCritical(env, 470 pixelsArray, pixels, JNI_ABORT); 471 return -1; 472 } 473 474 grad.p1.x = x1; 475 grad.p1.y = y1; 476 grad.p2.x = x2; 477 grad.p2.y = y2; 478 479 /*TODO optimized & malloc check*/ 480 colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor)); 481 stops = (XFixed *) malloc(numStops * sizeof(XFixed)); 482 483 for (i=0; i < numStops; i++) { 484 stops[i] = XDoubleToFixed(fractions[i]); 485 colors[i].alpha = pixels[i*4 + 0]; 486 colors[i].red = pixels[i*4 + 1]; 487 colors[i].green = pixels[i*4 + 2]; 488 colors[i].blue = pixels[i*4 + 3]; 489 } 490 #ifdef __solaris__ 491 if (XRenderCreateLinearGradientFunc!=NULL) { 492 gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops); 493 } 494 #else 495 gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops); 496 #endif 497 free(colors); 498 free(stops); 499 500 (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT); 501 (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT); 502 503 if (gradient != 0) { 504 BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12); 505 XRenderSetPictureTransform (awt_display, gradient, &tr); 506 pict_attr.repeat = repeat; 507 XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr); 508 } 509 510 return (jint) gradient; 511 } 512 513 514 JNIEXPORT jint JNICALL 515 Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative 516 (JNIEnv *env, jclass xsd, jfloatArray fractionsArray, 517 jshortArray pixelsArray, jint numStops, 518 jint innerRadius, jint outerRadius, jint repeat, 519 jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) { 520 jint i; 521 jshort* pixels; 522 jfloat* fractions; 523 XTransform tr; 524 XRenderPictureAttributes pict_attr; 525 Picture gradient = 0; 526 XRenderColor *colors; 527 XFixed *stops; 528 XRadialGradient grad; 529 530 531 if ((pixels = 532 (jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) { 533 return -1; 534 } 535 if ((fractions = (jfloat *) 536 (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) { 537 (*env)->ReleasePrimitiveArrayCritical(env, 538 pixelsArray, pixels, JNI_ABORT); 539 return -1; //TODO release pixels first 540 } 541 542 grad.inner.x = 0; 543 grad.inner.y = 0; 544 grad.inner.radius = innerRadius; 545 grad.outer.x = 0; 546 grad.outer.y = 0; 547 grad.outer.radius = outerRadius; 548 549 /*TODO optimized & malloc check*/ 550 colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor)); 551 stops = (XFixed *) malloc(numStops * sizeof(XFixed)); 552 553 for (i=0; i < numStops; i++) { 554 stops[i] = XDoubleToFixed(fractions[i]); 555 colors[i].alpha = pixels[i*4 + 0]; 556 colors[i].red = pixels[i*4 + 1]; 557 colors[i].green = pixels[i*4 + 2]; 558 colors[i].blue = pixels[i*4 + 3]; 559 } 560 #ifdef __solaris__ 561 if (XRenderCreateRadialGradientFunc != NULL) { 562 gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops); 563 } 564 #else 565 gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops); 566 #endif 567 free(colors); 568 free(stops); 569 570 (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT); 571 (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT); 572 573 574 if (gradient != 0) { 575 BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12); 576 XRenderSetPictureTransform (awt_display, gradient, &tr); 577 pict_attr.repeat = repeat; 578 XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr); 579 } 580 581 return (jint) gradient; 582 } 583 584 JNIEXPORT void JNICALL 585 Java_sun_java2d_xr_XRBackendNative_setFilter 586 (JNIEnv *env, jobject this, jint picture, jint filter) { 587 588 char * filterName = "fast"; 589 590 switch(filter) { 591 case 0: 592 filterName = "fast"; 593 break; 594 595 case 1: 596 filterName = "good"; 597 break; 598 599 case 2: 600 filterName = "best"; 601 break; 602 } 603 604 XRenderSetPictureFilter(awt_display, (Picture) picture, filterName, NULL, 0); 605 } 606 607 JNIEXPORT void JNICALL 608 Java_sun_java2d_xr_XRBackendNative_XRSetClipNative 609 (JNIEnv *env, jclass xsd, jlong dst, 610 jint x1, jint y1, jint x2, jint y2, 611 jobject complexclip, jboolean isGC) 612 { 613 int numrects; 614 XRectangle rects[256]; 615 XRectangle *pRect = rects; 616 617 numrects = RegionToYXBandedRectangles(env, 618 x1, y1, x2, y2, complexclip, 619 &pRect, 256); 620 621 if (isGC == JNI_TRUE) { 622 if (dst != (jlong) 0) { 623 XSetClipRectangles(awt_display, (GC) jlong_to_ptr(dst), 0, 0, pRect, numrects, YXBanded); 624 } 625 } else { 626 XRenderSetPictureClipRectangles (awt_display, (Picture) dst, 0, 0, pRect, numrects); 627 } 628 629 if (pRect != rects) { 630 free(pRect); 631 } 632 } 633 634 JNIEXPORT void JNICALL 635 Java_sun_java2d_xr_XRBackendNative_putMaskNative 636 (JNIEnv *env, jclass cls, jint drawable, jlong gc, jbyteArray imageData, 637 jint sx, jint sy, jint dx, jint dy, jint width, jint height, 638 jint maskOff, jint maskScan, jfloat ea, jlong imgPtr) { 639 640 int line, pix; 641 char *mask; 642 char *defaultData; 643 XImage *defaultImg, *img; 644 jboolean imageFits; 645 646 if ((mask = (char *) 647 (*env)->GetPrimitiveArrayCritical(env, imageData, NULL)) == NULL) { 648 return; 649 } 650 651 defaultImg = (XImage *) jlong_to_ptr(imgPtr); 652 653 if (ea != 1.0f) { 654 for (line=0; line < height; line++) { 655 for (pix=0; pix < width; pix++) { 656 int index = maskScan*line + pix + maskOff; 657 mask[index] = (((unsigned char) mask[index])*ea); 658 } 659 } 660 } 661 662 /* 663 * 1. If existing XImage and supplied buffer match, only adjust the data pointer 664 * 2. If existing XImage is large enough to hold the data but does not match in 665 * scan the data is copied to fit the XImage. 666 * 3. If data is larger than the existing XImage a new temporary XImage is 667 * allocated. 668 * The default XImage is optimized for the AA tiles, which are currently 32x32. 669 */ 670 defaultData = defaultImg->data; 671 img = defaultImg; 672 imageFits = defaultImg->width >= width && defaultImg->height >= height; 673 674 if (imageFits && 675 maskOff == defaultImg->xoffset && maskScan == defaultImg->bytes_per_line) { 676 defaultImg->data = mask; 677 } else { 678 if (imageFits) { 679 for (line=0; line < height; line++) { 680 for (pix=0; pix < width; pix++) { 681 img->data[line*img->bytes_per_line + pix] = 682 (unsigned char) (mask[maskScan*line + pix + maskOff]); 683 } 684 } 685 } else { 686 img = XCreateImage(awt_display, NULL, 8, ZPixmap, 687 maskOff, mask, maskScan, height, 8, 0); 688 } 689 } 690 691 XPutImage(awt_display, (Pixmap) drawable, (GC) jlong_to_ptr(gc), 692 img, 0, 0, 0, 0, width, height); 693 (*env)->ReleasePrimitiveArrayCritical(env, imageData, mask, JNI_ABORT); 694 695 if (img != defaultImg) { 696 img->data = NULL; 697 XDestroyImage(img); 698 } 699 defaultImg->data = defaultData; 700 } 701 702 JNIEXPORT void JNICALL 703 Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative 704 (JNIEnv *env, jclass cls, jint glyphSet, 705 jlongArray glyphInfoPtrsArray, jint glyphCnt, 706 jbyteArray pixelDataArray, int pixelDataLength) { 707 jlong *glyphInfoPtrs; 708 unsigned char *pixelData; 709 int i; 710 711 XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt); 712 Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt); 713 714 if (xginfo == NULL || gid == NULL) { 715 if (xginfo != NULL) { 716 free(xginfo); 717 } 718 if (gid != NULL) { 719 free(gid); 720 } 721 return; 722 } 723 724 if ((glyphInfoPtrs = (jlong *)(*env)-> 725 GetPrimitiveArrayCritical(env, glyphInfoPtrsArray, NULL)) == NULL) 726 { 727 free(xginfo); 728 free(gid); 729 return; 730 } 731 732 if ((pixelData = (unsigned char *) 733 (*env)->GetPrimitiveArrayCritical(env, pixelDataArray, NULL)) == NULL) 734 { 735 (*env)->ReleasePrimitiveArrayCritical(env, 736 glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT); 737 free(xginfo); 738 free(gid); 739 return; 740 } 741 742 for (i=0; i < glyphCnt; i++) { 743 GlyphInfo *jginfo = (GlyphInfo *) jlong_to_ptr(glyphInfoPtrs[i]); 744 745 gid[i] = (Glyph) (0x0ffffffffL & ((unsigned long)(jginfo->cellInfo))); 746 xginfo[i].x = (-jginfo->topLeftX); 747 xginfo[i].y = (-jginfo->topLeftY); 748 xginfo[i].width = jginfo->width; 749 xginfo[i].height = jginfo->height; 750 xginfo[i].xOff = round(jginfo->advanceX); 751 xginfo[i].yOff = round(jginfo->advanceY); 752 } 753 754 XRenderAddGlyphs(awt_display, glyphSet, &gid[0], &xginfo[0], glyphCnt, 755 (const char*)pixelData, pixelDataLength); 756 757 (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT); 758 (*env)->ReleasePrimitiveArrayCritical(env, pixelDataArray, pixelData, JNI_ABORT); 759 760 free(xginfo); 761 free(gid); 762 } 763 764 JNIEXPORT void JNICALL 765 Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative 766 (JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) { 767 768 /* The glyph ids are 32 bit but may be stored in a 64 bit long on 769 * a 64 bit architecture. So optimise the 32 bit case to avoid 770 * extra stack or heap allocations by directly referencing the 771 * underlying Java array and only allocate on 64 bit. 772 */ 773 if (sizeof(jint) == sizeof(Glyph)) { 774 jint *gids = 775 (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL); 776 if (gids == NULL) { 777 return; 778 } else { 779 XRenderFreeGlyphs(awt_display, 780 (GlyphSet)glyphSet, (Glyph *)gids, glyphCnt); 781 (*env)->ReleasePrimitiveArrayCritical(env, gidArray, 782 gids, JNI_ABORT); 783 } 784 return; 785 } else { 786 Glyph stack_ids[64]; 787 Glyph *gids = NULL; 788 jint* jgids = NULL; 789 int i; 790 791 if (glyphCnt <= 64) { 792 gids = stack_ids; 793 } else { 794 gids = (Glyph *)malloc(sizeof(Glyph) * glyphCnt); 795 if (gids == NULL) { 796 return; 797 } 798 } 799 jgids = (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL); 800 if (jgids == NULL) { 801 if (gids != stack_ids) { 802 free(gids); 803 } 804 return; 805 } 806 for (i=0; i < glyphCnt; i++) { 807 gids[i] = jgids[i]; 808 } 809 XRenderFreeGlyphs(awt_display, 810 (GlyphSet) glyphSet, gids, glyphCnt); 811 (*env)->ReleasePrimitiveArrayCritical(env, gidArray, 812 jgids, JNI_ABORT); 813 if (gids != stack_ids) { 814 free(gids); 815 } 816 } 817 } 818 819 JNIEXPORT jint JNICALL 820 Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative 821 (JNIEnv *env, jclass cls, jlong format) { 822 return XRenderCreateGlyphSet(awt_display, (XRenderPictFormat *) jlong_to_ptr(format)); 823 } 824 825 JNIEXPORT void JNICALL 826 Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative 827 (JNIEnv *env, jclass cls, jint op, jint src, jint dst, jlong maskFmt, 828 jintArray eltArray, jintArray glyphIDArray, jint eltCnt, jint glyphCnt) { 829 jint i; 830 jint *ids; 831 jint *elts; 832 XGlyphElt32 *xelts; 833 unsigned int *xids; 834 XGlyphElt32 selts[24]; 835 unsigned int sids[256]; 836 int charCnt = 0; 837 838 if (eltCnt <= 24) { 839 xelts = &selts[0]; 840 }else { 841 xelts = (XGlyphElt32 *) malloc(sizeof(XGlyphElt32) * eltCnt); 842 if (xelts == NULL) { 843 return; 844 } 845 } 846 847 if (glyphCnt <= 256) { 848 xids = &sids[0]; 849 } else { 850 xids = (unsigned int*)malloc(sizeof(unsigned int) * glyphCnt); 851 if (xids == NULL) { 852 if (xelts != &selts[0]) { 853 free(xelts); 854 } 855 return; 856 } 857 } 858 859 if ((ids = (jint *) 860 (*env)->GetPrimitiveArrayCritical(env, glyphIDArray, NULL)) == NULL) { 861 if (xelts != &selts[0]) { 862 free(xelts); 863 } 864 if (xids != &sids[0]) { 865 free(xids); 866 } 867 return; 868 } 869 if ((elts = (jint *) 870 (*env)->GetPrimitiveArrayCritical(env, eltArray, NULL)) == NULL) { 871 (*env)->ReleasePrimitiveArrayCritical(env, 872 glyphIDArray, ids, JNI_ABORT); 873 if (xelts != &selts[0]) { 874 free(xelts); 875 } 876 if (xids != &sids[0]) { 877 free(xids); 878 } 879 return; 880 } 881 882 for (i=0; i < glyphCnt; i++) { 883 xids[i] = ids[i]; 884 } 885 886 for (i=0; i < eltCnt; i++) { 887 xelts[i].nchars = elts[i*4 + 0]; 888 xelts[i].xOff = elts[i*4 + 1]; 889 xelts[i].yOff = elts[i*4 + 2]; 890 xelts[i].glyphset = (GlyphSet) elts[i*4 + 3]; 891 xelts[i].chars = &xids[charCnt]; 892 893 charCnt += xelts[i].nchars; 894 } 895 896 XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst, 897 (XRenderPictFormat *) jlong_to_ptr(maskFmt), 898 0, 0, 0, 0, xelts, eltCnt); 899 900 (*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT); 901 (*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT); 902 903 if (xelts != &selts[0]) { 904 free(xelts); 905 } 906 907 if (xids != &sids[0]) { 908 free(xids); 909 } 910 } 911 912 JNIEXPORT void JNICALL 913 Java_sun_java2d_xr_XRBackendNative_setGCMode 914 (JNIEnv *env, jobject this, jlong gc, jboolean copy) { 915 GC xgc = (GC) jlong_to_ptr(gc); 916 917 if (copy == JNI_TRUE) { 918 XSetFunction(awt_display, xgc, GXcopy); 919 } else { 920 XSetFunction(awt_display, xgc, GXxor); 921 } 922 } 923 924 JNIEXPORT void JNICALL 925 Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative 926 (JNIEnv *env, jclass xsd, jint dst, jlong gc, 927 jintArray rectArray, jint rectCnt) { 928 int i; 929 jint* rects; 930 XRectangle *xRects; 931 XRectangle sRects[256]; 932 933 if (rectCnt <= 256) { 934 xRects = &sRects[0]; 935 } else { 936 xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt); 937 if (xRects == NULL) { 938 return; 939 } 940 } 941 942 if ((rects = (jint*) 943 (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) { 944 if (xRects != &sRects[0]) { 945 free(xRects); 946 } 947 return; 948 } 949 950 for (i=0; i < rectCnt; i++) { 951 xRects[i].x = rects[i*4 + 0]; 952 xRects[i].y = rects[i*4 + 1]; 953 xRects[i].width = rects[i*4 + 2]; 954 xRects[i].height = rects[i*4 + 3]; 955 } 956 957 XFillRectangles(awt_display, (Drawable) dst, (GC) jlong_to_ptr(gc), xRects, rectCnt); 958 959 (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT); 960 if (xRects != &sRects[0]) { 961 free(xRects); 962 } 963 } 964 965 JNIEXPORT void JNICALL 966 Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative 967 (JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt, 968 jint dst, jint srcX, jint srcY, jintArray trapArray) { 969 jint *traps; 970 971 if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) { 972 return; 973 } 974 975 XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst, 976 (XRenderPictFormat *) jlong_to_ptr(maskFmt), 977 srcX, srcY, (XTrapezoid *) (traps+5), traps[0]); 978 979 (*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT); 980 }