2370N/A/*
3909N/A * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
2370N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2370N/A *
2370N/A * This code is free software; you can redistribute it and/or modify it
2370N/A * under the terms of the GNU General Public License version 2 only, as
2685N/A * published by the Free Software Foundation. Oracle designates this
2370N/A * particular file as subject to the "Classpath" exception as provided
2685N/A * by Oracle in the LICENSE file that accompanied this code.
2370N/A *
2370N/A * This code is distributed in the hope that it will be useful, but WITHOUT
2370N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2370N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2370N/A * version 2 for more details (a copy is included in the LICENSE file that
2370N/A * accompanied this code).
2370N/A *
2370N/A * You should have received a copy of the GNU General Public License version
2370N/A * 2 along with this work; if not, write to the Free Software Foundation,
2370N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2370N/A *
2685N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2685N/A * or visit www.oracle.com if you need additional information or have any
2685N/A * questions.
2370N/A */
2370N/A
2370N/A#include "X11SurfaceData.h"
2370N/A#include <jni.h>
2370N/A#include <math.h>
2370N/A#include "Region.h"
2370N/A#include "fontscalerdefs.h"
2370N/A
2370N/A#include <X11/extensions/Xrender.h>
2370N/A
3344N/A/* On Solaris 10 updates 8, 9, the render.h file defines these
3344N/A * protocol values but does not define the structs in Xrender.h.
3344N/A * Thus in order to get these always defined on Solaris 10
3344N/A * we will undefine the symbols if we have determined via the
3344N/A * makefiles that Xrender.h is lacking the structs. This will
3344N/A * trigger providing our own definitions as on earlier updates.
3344N/A * We could assume that *all* Solaris 10 update versions will lack the updated
3344N/A * Xrender.h and do this based solely on O/S being any 5.10 version, but this
3344N/A * could still change and we'd be broken again as we'd be re-defining them.
3344N/A */
3344N/A#ifdef SOLARIS10_NO_XRENDER_STRUCTS
3344N/A#undef X_RenderCreateLinearGradient
3344N/A#undef X_RenderCreateRadialGradient
3344N/A#endif
3344N/A
2370N/A#ifndef X_RenderCreateLinearGradient
2370N/Atypedef struct _XLinearGradient {
2370N/A XPointFixed p1;
2370N/A XPointFixed p2;
2370N/A} XLinearGradient;
2370N/A#endif
2370N/A
2370N/A#ifndef X_RenderCreateRadialGradient
2370N/Atypedef struct _XCircle {
2370N/A XFixed x;
2370N/A XFixed y;
2370N/A XFixed radius;
2370N/A} XCircle;
2370N/A
2370N/Atypedef struct _XRadialGradient {
2370N/A XCircle inner;
2370N/A XCircle outer;
2370N/A} XRadialGradient;
2370N/A#endif
2370N/A
4258N/A#include <dlfcn.h>
4258N/A
2370N/A#ifdef __solaris__
2370N/A/* Solaris 10 will not have these symbols at runtime */
2370N/A
2370N/Atypedef Picture (*XRenderCreateLinearGradientFuncType)
2370N/A (Display *dpy,
2370N/A const XLinearGradient *gradient,
2370N/A const XFixed *stops,
2370N/A const XRenderColor *colors,
2370N/A int nstops);
2370N/A
2370N/Atypedef Picture (*XRenderCreateRadialGradientFuncType)
2370N/A (Display *dpy,
2370N/A const XRadialGradient *gradient,
2370N/A const XFixed *stops,
2370N/A const XRenderColor *colors,
2370N/A int nstops);
2370N/A
2370N/Astatic
2370N/AXRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;
2370N/Astatic
2370N/A XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;
2370N/A#endif
2370N/A
2370N/A#define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \
2370N/A { \
2370N/A TRANSFORM.matrix[0][0] = M00; \
2370N/A TRANSFORM.matrix[0][1] = M01; \
2370N/A TRANSFORM.matrix[0][2] = M02; \
2370N/A TRANSFORM.matrix[1][0] = M10; \
2370N/A TRANSFORM.matrix[1][1] = M11; \
2370N/A TRANSFORM.matrix[1][2] = M12; \
2370N/A TRANSFORM.matrix[2][0] = 0; \
2370N/A TRANSFORM.matrix[2][1] = 0; \
2370N/A TRANSFORM.matrix[2][2] = 1<<16; \
2370N/A }
2370N/A
4258N/A/* The xrender pipleine requires libXrender.so version 0.9.3 or later. */
4258N/A#define REQUIRED_XRENDER_VER1 0
4258N/A#define REQUIRED_XRENDER_VER2 9
4258N/A#define REQUIRED_XRENDER_VER3 3
2370N/A
4258N/A#define PKGINFO_LINE_LEN_MAX 256
4258N/A#define PKGINFO_LINE_CNT_MAX 50
4258N/A
4258N/Astatic jboolean IsXRenderAvailable(jboolean verbose) {
2370N/A
2370N/A void *xrenderlib;
2370N/A
2370N/A int major_opcode, first_event, first_error;
4258N/A jboolean available = JNI_TRUE;
2370N/A
2370N/A if (!XQueryExtension(awt_display, "RENDER",
2370N/A &major_opcode, &first_event, &first_error)) {
2370N/A return JNI_FALSE;
2370N/A }
2370N/A
2370N/A#ifdef __solaris__
2370N/A xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
2370N/A if (xrenderlib != NULL) {
2370N/A
4258N/A XRenderCreateLinearGradientFunc =
4258N/A (XRenderCreateLinearGradientFuncType)
4258N/A dlsym(xrenderlib, "XRenderCreateLinearGradient");
4258N/A
4258N/A XRenderCreateRadialGradientFunc =
4258N/A (XRenderCreateRadialGradientFuncType)
4258N/A dlsym(xrenderlib, "XRenderCreateRadialGradient");
4258N/A
4258N/A if (XRenderCreateLinearGradientFunc == NULL ||
4258N/A XRenderCreateRadialGradientFunc == NULL)
4258N/A {
4258N/A available = JNI_FALSE;
4258N/A }
4258N/A dlclose(xrenderlib);
4258N/A } else {
4258N/A available = JNI_FALSE;
4258N/A }
4258N/A#else
4258N/A Dl_info info;
4258N/A jboolean versionInfoIsFound = JNI_FALSE;
4258N/A
4258N/A memset(&info, 0, sizeof(Dl_info));
4258N/A if (dladdr(&XRenderChangePicture, &info) && info.dli_fname != NULL) {
4258N/A char pkgInfoPath[FILENAME_MAX];
4258N/A char *pkgFileName = "/pkgconfig/xrender.pc";
4258N/A size_t pkgFileNameLen = strlen(pkgFileName);
4258N/A size_t pos, len = strlen(info.dli_fname);
4258N/A
4258N/A pos = len;
4258N/A while (pos > 0 && info.dli_fname[pos] != '/') {
4258N/A pos -= 1;
4258N/A }
4258N/A
4258N/A if (pos > 0 && pos < (FILENAME_MAX - pkgFileNameLen - 1)) {
4258N/A struct stat stat_info;
4258N/A
4258N/A // compose absolute filename to package config
4258N/A strncpy(pkgInfoPath, info.dli_fname, pos);
4258N/A
4258N/A strcpy(pkgInfoPath + pos, pkgFileName);
4258N/A pkgInfoPath[pos + pkgFileNameLen] = '\0';
2370N/A
4258N/A // check whether the config file exist and is a regular file
4258N/A if ((stat(pkgInfoPath, &stat_info)== 0) &&
4258N/A S_ISREG(stat_info.st_mode))
4258N/A {
4258N/A FILE *fp = fopen(pkgInfoPath, "r");
4258N/A if (fp != NULL) {
4258N/A char line[PKGINFO_LINE_LEN_MAX];
4258N/A int lineCount = PKGINFO_LINE_CNT_MAX;
4258N/A char *versionPrefix = "Version: ";
4258N/A size_t versionPrefixLen = strlen(versionPrefix);
4258N/A
4258N/A // look for version
4258N/A while(fgets(line,sizeof(line),fp) != NULL && --lineCount > 0) {
4258N/A size_t lineLen = strlen(line);
4258N/A
4258N/A if (lineLen > versionPrefixLen &&
4258N/A strncmp(versionPrefix, line, versionPrefixLen) == 0)
4258N/A {
4258N/A int v1 = 0, v2 = 0, v3 = 0;
4258N/A int numNeeded = 3,numProcessed;
4258N/A char* version = line + versionPrefixLen;
4258N/A numProcessed = sscanf(version, "%d.%d.%d", &v1, &v2, &v3);
4258N/A
4258N/A if (numProcessed == numNeeded) {
4258N/A // we successfuly read the library version
4258N/A versionInfoIsFound = JNI_TRUE;
2370N/A
4258N/A if (REQUIRED_XRENDER_VER1 == v1 &&
4258N/A ((REQUIRED_XRENDER_VER2 > v2) ||
4258N/A ((REQUIRED_XRENDER_VER2 == v2) && (REQUIRED_XRENDER_VER3 > v3))))
4258N/A {
4258N/A available = JNI_FALSE;
4258N/A
4258N/A if (verbose) {
4258N/A printf("INFO: the version %d.%d.%d of libXrender.so is "
4258N/A "not supported.\n\tSee release notes for more details.\n",
4258N/A v1, v2, v3);
4258N/A fflush(stdout);
4258N/A }
4258N/A } else {
4258N/A if (verbose) {
4258N/A printf("INFO: The version of libXrender.so "
4258N/A "is detected as %d.%d%d\n", v1, v2, v3);
4258N/A fflush(stdout);
4258N/A }
4258N/A }
4258N/A }
4258N/A break;
4258N/A }
4258N/A }
4258N/A fclose(fp);
4258N/A }
2370N/A }
4258N/A }
4258N/A }
4258N/A if (verbose && !versionInfoIsFound) {
4258N/A printf("WARNING: The version of libXrender.so cannot be detected.\n,"
4258N/A "The pipe line will be enabled, but note that versions less than 0.9.3\n"
4258N/A "may cause hangs and crashes\n"
4258N/A "\tSee the release notes for more details.\n");
4258N/A fflush(stdout);
2370N/A }
2370N/A#endif
4258N/A
4258N/A return available;
2370N/A}
2370N/A/*
2370N/A * Class: sun_awt_X11GraphicsEnvironment
2370N/A * Method: initGLX
2370N/A * Signature: ()Z
2370N/A */
2370N/AJNIEXPORT jboolean JNICALL
2370N/AJava_sun_awt_X11GraphicsEnvironment_initXRender
4258N/A(JNIEnv *env, jclass x11ge, jboolean verbose)
2370N/A{
2370N/A#ifndef HEADLESS
2370N/A static jboolean xrenderAvailable = JNI_FALSE;
2370N/A static jboolean firstTime = JNI_TRUE;
2370N/A
2370N/A if (firstTime) {
2370N/A AWT_LOCK();
4258N/A xrenderAvailable = IsXRenderAvailable(verbose);
2370N/A AWT_UNLOCK();
2370N/A firstTime = JNI_FALSE;
2370N/A }
2370N/A return xrenderAvailable;
2370N/A#else
2370N/A return JNI_FALSE;
2370N/A#endif /* !HEADLESS */
2370N/A}
2370N/A
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_initIDs(JNIEnv *env, jclass cls) {
2370N/A char *maskData;
2370N/A XImage* defaultImg;
2370N/A jfieldID maskImgID;
2370N/A jlong fmt8 =
2370N/A ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardA8));
2370N/A jlong fmt32 =
2370N/A ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardARGB32));
2370N/A jfieldID a8ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_A8", "J");
2370N/A jfieldID argb32ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_ARGB32", "J");
2370N/A
2370N/A (*env)->SetStaticLongField(env, cls, a8ID, fmt8);
2370N/A (*env)->SetStaticLongField(env, cls, argb32ID, fmt32);
2370N/A
2370N/A maskData = (char *) malloc(32*32);
2370N/A if (maskData == NULL) {
2370N/A return;
2370N/A }
2370N/A
2370N/A defaultImg = XCreateImage(awt_display, NULL, 8, ZPixmap, 0, maskData, 32, 32, 8, 0);
2370N/A defaultImg->data = maskData; //required?
2370N/A maskImgID = (*env)->GetStaticFieldID(env, cls, "MASK_XIMG", "J");
2370N/A (*env)->SetStaticLongField(env, cls, maskImgID, ptr_to_jlong(defaultImg));
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_freeGC
2370N/A (JNIEnv *env, jobject this, jlong gc) {
2370N/A XFreeGC(awt_display, (GC) jlong_to_ptr(gc));
2370N/A}
2370N/A
2370N/AJNIEXPORT jlong JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_createGC
2370N/A (JNIEnv *env, jobject this, jint drawable) {
2370N/A GC xgc = XCreateGC(awt_display, (Drawable) drawable, 0L, NULL);
2370N/A return ptr_to_jlong(xgc);
2370N/A}
2370N/A
2370N/AJNIEXPORT jint JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_createPixmap(JNIEnv *env, jobject this,
2370N/A jint drawable, jint depth,
2370N/A jint width, jint height) {
2370N/A return (jint) XCreatePixmap(awt_display, (Drawable) drawable,
2370N/A width, height, depth);
2370N/A}
2370N/A
2370N/AJNIEXPORT jint JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_createPictureNative
2370N/A (JNIEnv *env, jclass cls, jint drawable, jlong formatPtr) {
2370N/A XRenderPictureAttributes pict_attr;
2370N/A return XRenderCreatePicture(awt_display, (Drawable) drawable,
2370N/A (XRenderPictFormat *) jlong_to_ptr(formatPtr),
2370N/A 0, &pict_attr);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_freePicture
2370N/A (JNIEnv *env, jobject this, jint picture) {
2370N/A XRenderFreePicture(awt_display, (Picture) picture);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_freePixmap
2370N/A (JNIEnv *env, jobject this, jint pixmap) {
2370N/A XFreePixmap(awt_display, (Pixmap) pixmap);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_setPictureRepeat
2370N/A (JNIEnv *env, jobject this, jint picture, jint repeat) {
2370N/A XRenderPictureAttributes pict_attr;
2370N/A pict_attr.repeat = repeat;
2370N/A XRenderChangePicture (awt_display, (Picture) picture, CPRepeat, &pict_attr);
2370N/A}
2370N/A
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_setGCExposures
2370N/A (JNIEnv *env, jobject this, jlong gc, jboolean exposure) {
2370N/A XSetGraphicsExposures(awt_display,
2370N/A (GC) jlong_to_ptr(gc), exposure ? True : False); //TODO: ????
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_setGCForeground
2370N/A (JNIEnv *env, jobject this, jlong gc, jint pixel) {
2370N/A XSetForeground(awt_display, (GC) jlong_to_ptr(gc), (unsigned long) pixel);
2370N/A}
2370N/A
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_copyArea
2370N/A (JNIEnv *env, jobject this, jint src, jint dst, jlong gc,
2370N/A jint srcx, jint srcy, jint width, jint height, jint dstx, jint dsty) {
2370N/A XCopyArea(awt_display, (Drawable) src, (Drawable) dst,
2370N/A (GC) jlong_to_ptr(gc), srcx, srcy, width, height, dstx, dsty);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_renderComposite
2370N/A (JNIEnv *env, jobject this, jbyte op, jint src, jint mask, jint dst,
2370N/A jint srcX, jint srcY, jint maskX, jint maskY,
2370N/A jint dstX, jint dstY, jint width, jint height) {
2370N/A XRenderComposite (awt_display, op,
2370N/A (Picture)src, (Picture)mask, (Picture)dst,
2370N/A srcX, srcY, maskX, maskY, dstX, dstY, width, height);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_renderRectangle
2370N/A (JNIEnv *env, jobject this, jint dst, jbyte op,
2370N/A jshort red, jshort green, jshort blue, jshort alpha,
2370N/A jint x, jint y, jint width, jint height) {
2370N/A XRenderColor color;
2370N/A color.alpha = alpha;
2370N/A color.red = red;
2370N/A color.green = green;
2370N/A color.blue = blue;
2370N/A XRenderFillRectangle(awt_display, op, (Picture) dst, &color,
2370N/A x, y, width, height);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative
2370N/A (JNIEnv *env, jclass xsd, jint dst, jbyte op,
2370N/A jshort red, jshort green, jshort blue, jshort alpha,
2370N/A jintArray rectArray, jint rectCnt) {
2370N/A int i;
2370N/A jint* rects;
2370N/A XRectangle *xRects;
2370N/A XRectangle sRects[256];
2370N/A
2370N/A XRenderColor color;
2370N/A color.alpha = alpha;
2370N/A color.red = red;
2370N/A color.green = green;
2370N/A color.blue = blue;
2370N/A
2370N/A if (rectCnt <= 256) {
3609N/A xRects = &sRects[0];
2370N/A } else {
3609N/A xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
3609N/A if (xRects == NULL) {
3609N/A return;
3609N/A }
2370N/A }
2370N/A
3609N/A if ((rects = (jint *)
3609N/A (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
3609N/A if (xRects != &sRects[0]) {
3609N/A free(xRects);
3609N/A }
3609N/A return;
2370N/A }
2370N/A
2370N/A for (i=0; i < rectCnt; i++) {
3609N/A xRects[i].x = rects[i*4 + 0];
3609N/A xRects[i].y = rects[i*4 + 1];
3609N/A xRects[i].width = rects[i*4 + 2];
3609N/A xRects[i].height = rects[i*4 + 3];
2370N/A }
2370N/A
2370N/A XRenderFillRectangles(awt_display, op,
2370N/A (Picture) dst, &color, xRects, rectCnt);
2370N/A
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
2370N/A if (xRects != &sRects[0]) {
3609N/A free(xRects);
2370N/A }
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRSetTransformNative
2370N/A (JNIEnv *env, jclass xsd, jint pic,
2370N/A jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
2370N/A
2370N/A XTransform tr;
2370N/A BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
2370N/A XRenderSetPictureTransform (awt_display, (Picture) pic, &tr);
2370N/A}
2370N/A
2370N/AJNIEXPORT jint JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative
2370N/A (JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
2370N/A jshortArray pixelsArray, jint x1, jint y1, jint x2, jint y2,
2370N/A jint numStops, jint repeat,
2370N/A jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
2370N/A jint i;
2370N/A jshort* pixels;
2370N/A jfloat* fractions;
2370N/A XTransform tr;
2370N/A XRenderPictureAttributes pict_attr;
2370N/A Picture gradient = 0;
2370N/A XRenderColor *colors;
2370N/A XFixed *stops;
2370N/A XLinearGradient grad;
2370N/A
2370N/A if ((pixels = (jshort *)
2370N/A (*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
2370N/A return -1;
2370N/A }
2370N/A if ((fractions = (jfloat *)
2370N/A (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
2370N/A (*env)->ReleasePrimitiveArrayCritical(env,
2370N/A pixelsArray, pixels, JNI_ABORT);
2370N/A return -1;
2370N/A }
2370N/A
2370N/A grad.p1.x = x1;
2370N/A grad.p1.y = y1;
2370N/A grad.p2.x = x2;
2370N/A grad.p2.y = y2;
2370N/A
2370N/A /*TODO optimized & malloc check*/
2370N/A colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
2370N/A stops = (XFixed *) malloc(numStops * sizeof(XFixed));
2370N/A
2370N/A for (i=0; i < numStops; i++) {
2370N/A stops[i] = XDoubleToFixed(fractions[i]);
2370N/A colors[i].alpha = pixels[i*4 + 0];
2370N/A colors[i].red = pixels[i*4 + 1];
2370N/A colors[i].green = pixels[i*4 + 2];
2370N/A colors[i].blue = pixels[i*4 + 3];
2370N/A }
2370N/A#ifdef __solaris__
2370N/A if (XRenderCreateLinearGradientFunc!=NULL) {
2370N/A gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);
2370N/A }
2370N/A#else
2370N/A gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);
2370N/A#endif
2370N/A free(colors);
2370N/A free(stops);
2370N/A
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
2370N/A
2370N/A if (gradient != 0) {
2370N/A BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
2370N/A XRenderSetPictureTransform (awt_display, gradient, &tr);
2370N/A pict_attr.repeat = repeat;
2370N/A XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
2370N/A }
2370N/A
2370N/A return (jint) gradient;
2370N/A}
2370N/A
2370N/A
2370N/AJNIEXPORT jint JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative
2370N/A (JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
2370N/A jshortArray pixelsArray, jint numStops,
2370N/A jint innerRadius, jint outerRadius, jint repeat,
2370N/A jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
2370N/A jint i;
2370N/A jshort* pixels;
2370N/A jfloat* fractions;
2370N/A XTransform tr;
2370N/A XRenderPictureAttributes pict_attr;
2370N/A Picture gradient = 0;
2370N/A XRenderColor *colors;
2370N/A XFixed *stops;
2370N/A XRadialGradient grad;
2370N/A
2370N/A
2370N/A if ((pixels =
2370N/A (jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
2370N/A return -1;
2370N/A }
2370N/A if ((fractions = (jfloat *)
2370N/A (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
2370N/A (*env)->ReleasePrimitiveArrayCritical(env,
2370N/A pixelsArray, pixels, JNI_ABORT);
2370N/A return -1; //TODO release pixels first
2370N/A }
2370N/A
2370N/A grad.inner.x = 0;
2370N/A grad.inner.y = 0;
2370N/A grad.inner.radius = innerRadius;
2370N/A grad.outer.x = 0;
2370N/A grad.outer.y = 0;
2370N/A grad.outer.radius = outerRadius;
2370N/A
2370N/A /*TODO optimized & malloc check*/
2370N/A colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
2370N/A stops = (XFixed *) malloc(numStops * sizeof(XFixed));
2370N/A
2370N/A for (i=0; i < numStops; i++) {
2370N/A stops[i] = XDoubleToFixed(fractions[i]);
2370N/A colors[i].alpha = pixels[i*4 + 0];
2370N/A colors[i].red = pixels[i*4 + 1];
2370N/A colors[i].green = pixels[i*4 + 2];
2370N/A colors[i].blue = pixels[i*4 + 3];
2370N/A }
2370N/A#ifdef __solaris__
2370N/A if (XRenderCreateRadialGradientFunc != NULL) {
2370N/A gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);
2370N/A }
2370N/A#else
2370N/A gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);
2370N/A#endif
2370N/A free(colors);
2370N/A free(stops);
2370N/A
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
2370N/A
2370N/A
2370N/A if (gradient != 0) {
2370N/A BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
2370N/A XRenderSetPictureTransform (awt_display, gradient, &tr);
2370N/A pict_attr.repeat = repeat;
2370N/A XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
2370N/A }
2370N/A
2370N/A return (jint) gradient;
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_setFilter
2370N/A (JNIEnv *env, jobject this, jint picture, jint filter) {
2370N/A
2370N/A char * filterName = "fast";
2370N/A
2370N/A switch(filter) {
2370N/A case 0:
2370N/A filterName = "fast";
2370N/A break;
2370N/A
2370N/A case 1:
2370N/A filterName = "good";
2370N/A break;
2370N/A
2370N/A case 2:
2370N/A filterName = "best";
2370N/A break;
2370N/A }
2370N/A
2370N/A XRenderSetPictureFilter(awt_display, (Picture) picture, filterName, NULL, 0);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRSetClipNative
2370N/A (JNIEnv *env, jclass xsd, jlong dst,
2370N/A jint x1, jint y1, jint x2, jint y2,
2370N/A jobject complexclip, jboolean isGC)
2370N/A{
2370N/A int numrects;
2370N/A XRectangle rects[256];
2370N/A XRectangle *pRect = rects;
2370N/A
2370N/A numrects = RegionToYXBandedRectangles(env,
2370N/A x1, y1, x2, y2, complexclip,
2370N/A &pRect, 256);
2370N/A
2370N/A if (isGC == JNI_TRUE) {
2370N/A if (dst != (jlong) 0) {
2370N/A XSetClipRectangles(awt_display, (GC) jlong_to_ptr(dst), 0, 0, pRect, numrects, YXBanded);
2370N/A }
2370N/A } else {
2370N/A XRenderSetPictureClipRectangles (awt_display, (Picture) dst, 0, 0, pRect, numrects);
2370N/A }
2370N/A
2370N/A if (pRect != rects) {
2370N/A free(pRect);
2370N/A }
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_putMaskNative
2370N/A (JNIEnv *env, jclass cls, jint drawable, jlong gc, jbyteArray imageData,
2370N/A jint sx, jint sy, jint dx, jint dy, jint width, jint height,
2370N/A jint maskOff, jint maskScan, jfloat ea, jlong imgPtr) {
2370N/A
2370N/A int line, pix;
2370N/A char *mask;
2370N/A char *defaultData;
2370N/A XImage *defaultImg, *img;
2370N/A jboolean imageFits;
2370N/A
2370N/A if ((mask = (char *)
2370N/A (*env)->GetPrimitiveArrayCritical(env, imageData, NULL)) == NULL) {
2370N/A return;
2370N/A }
2370N/A
2370N/A defaultImg = (XImage *) jlong_to_ptr(imgPtr);
2370N/A
2370N/A if (ea != 1.0f) {
2370N/A for (line=0; line < height; line++) {
2370N/A for (pix=0; pix < width; pix++) {
2370N/A int index = maskScan*line + pix + maskOff;
2370N/A mask[index] = (((unsigned char) mask[index])*ea);
2370N/A }
2370N/A }
2370N/A }
2370N/A
2370N/A /*
2370N/A * 1. If existing XImage and supplied buffer match, only adjust the data pointer
2370N/A * 2. If existing XImage is large enough to hold the data but does not match in
2370N/A * scan the data is copied to fit the XImage.
2370N/A * 3. If data is larger than the existing XImage a new temporary XImage is
2370N/A * allocated.
2370N/A * The default XImage is optimized for the AA tiles, which are currently 32x32.
2370N/A */
2370N/A defaultData = defaultImg->data;
2370N/A img = defaultImg;
2370N/A imageFits = defaultImg->width >= width && defaultImg->height >= height;
2370N/A
2370N/A if (imageFits &&
2370N/A maskOff == defaultImg->xoffset && maskScan == defaultImg->bytes_per_line) {
2370N/A defaultImg->data = mask;
2370N/A } else {
2370N/A if (imageFits) {
2370N/A for (line=0; line < height; line++) {
2370N/A for (pix=0; pix < width; pix++) {
2370N/A img->data[line*img->bytes_per_line + pix] =
2370N/A (unsigned char) (mask[maskScan*line + pix + maskOff]);
2370N/A }
2370N/A }
2370N/A } else {
2370N/A img = XCreateImage(awt_display, NULL, 8, ZPixmap,
2370N/A maskOff, mask, maskScan, height, 8, 0);
2370N/A }
2370N/A }
2370N/A
2370N/A XPutImage(awt_display, (Pixmap) drawable, (GC) jlong_to_ptr(gc),
2370N/A img, 0, 0, 0, 0, width, height);
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, imageData, mask, JNI_ABORT);
2370N/A
2370N/A if (img != defaultImg) {
2370N/A img->data = NULL;
2370N/A XDestroyImage(img);
2370N/A }
2370N/A defaultImg->data = defaultData;
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative
2370N/A (JNIEnv *env, jclass cls, jint glyphSet,
2370N/A jlongArray glyphInfoPtrsArray, jint glyphCnt,
2370N/A jbyteArray pixelDataArray, int pixelDataLength) {
2370N/A jlong *glyphInfoPtrs;
2370N/A unsigned char *pixelData;
2370N/A int i;
2370N/A
2370N/A XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt);
2370N/A Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);
2370N/A
2370N/A if (xginfo == NULL || gid == NULL) {
3609N/A if (xginfo != NULL) {
3609N/A free(xginfo);
3609N/A }
3609N/A if (gid != NULL) {
3609N/A free(gid);
3609N/A }
3609N/A return;
2370N/A }
2370N/A
3609N/A if ((glyphInfoPtrs = (jlong *)(*env)->
3609N/A GetPrimitiveArrayCritical(env, glyphInfoPtrsArray, NULL)) == NULL)
3609N/A {
3609N/A free(xginfo);
3609N/A free(gid);
2370N/A return;
2370N/A }
2370N/A
2370N/A if ((pixelData = (unsigned char *)
3609N/A (*env)->GetPrimitiveArrayCritical(env, pixelDataArray, NULL)) == NULL)
3609N/A {
2370N/A (*env)->ReleasePrimitiveArrayCritical(env,
3609N/A glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
3609N/A free(xginfo);
3609N/A free(gid);
2370N/A return;
2370N/A }
2370N/A
2370N/A for (i=0; i < glyphCnt; i++) {
2370N/A GlyphInfo *jginfo = (GlyphInfo *) jlong_to_ptr(glyphInfoPtrs[i]);
2370N/A
6133N/A // 'jginfo->cellInfo' is of type 'void*'
6133N/A // (see definition of 'GlyphInfo' in fontscalerdefs.h)
6133N/A // 'Glyph' is typedefed to 'unsigned long'
6133N/A // (see http://www.x.org/releases/X11R7.7/doc/libXrender/libXrender.txt)
6133N/A // Maybe we should assert that (sizeof(void*) == sizeof(Glyph)) ?
6133N/A gid[i] = (Glyph) (jginfo->cellInfo);
2370N/A xginfo[i].x = (-jginfo->topLeftX);
2370N/A xginfo[i].y = (-jginfo->topLeftY);
2370N/A xginfo[i].width = jginfo->width;
2370N/A xginfo[i].height = jginfo->height;
2370N/A xginfo[i].xOff = round(jginfo->advanceX);
2370N/A xginfo[i].yOff = round(jginfo->advanceY);
2370N/A }
2370N/A
2370N/A XRenderAddGlyphs(awt_display, glyphSet, &gid[0], &xginfo[0], glyphCnt,
3609N/A (const char*)pixelData, pixelDataLength);
2370N/A
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, pixelDataArray, pixelData, JNI_ABORT);
2370N/A
2370N/A free(xginfo);
2370N/A free(gid);
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative
2370N/A (JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) {
2370N/A
3818N/A /* The glyph ids are 32 bit but may be stored in a 64 bit long on
3818N/A * a 64 bit architecture. So optimise the 32 bit case to avoid
3818N/A * extra stack or heap allocations by directly referencing the
3818N/A * underlying Java array and only allocate on 64 bit.
3818N/A */
3818N/A if (sizeof(jint) == sizeof(Glyph)) {
3818N/A jint *gids =
3818N/A (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL);
3818N/A if (gids == NULL) {
3818N/A return;
3818N/A } else {
3818N/A XRenderFreeGlyphs(awt_display,
3818N/A (GlyphSet)glyphSet, (Glyph *)gids, glyphCnt);
3818N/A (*env)->ReleasePrimitiveArrayCritical(env, gidArray,
3818N/A gids, JNI_ABORT);
3818N/A }
2370N/A return;
3818N/A } else {
3818N/A Glyph stack_ids[64];
3818N/A Glyph *gids = NULL;
3818N/A jint* jgids = NULL;
3818N/A int i;
2370N/A
3818N/A if (glyphCnt <= 64) {
3818N/A gids = stack_ids;
3818N/A } else {
3818N/A gids = (Glyph *)malloc(sizeof(Glyph) * glyphCnt);
3818N/A if (gids == NULL) {
3818N/A return;
3818N/A }
3818N/A }
3818N/A jgids = (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL);
3818N/A if (jgids == NULL) {
3818N/A if (gids != stack_ids) {
3818N/A free(gids);
3818N/A }
3818N/A return;
3818N/A }
3818N/A for (i=0; i < glyphCnt; i++) {
3818N/A gids[i] = jgids[i];
3818N/A }
3818N/A XRenderFreeGlyphs(awt_display,
3818N/A (GlyphSet) glyphSet, gids, glyphCnt);
3818N/A (*env)->ReleasePrimitiveArrayCritical(env, gidArray,
3818N/A jgids, JNI_ABORT);
3818N/A if (gids != stack_ids) {
3818N/A free(gids);
3818N/A }
3818N/A }
2370N/A}
2370N/A
2370N/AJNIEXPORT jint JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative
2370N/A (JNIEnv *env, jclass cls, jlong format) {
2370N/A return XRenderCreateGlyphSet(awt_display, (XRenderPictFormat *) jlong_to_ptr(format));
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative
2370N/A (JNIEnv *env, jclass cls, jint op, jint src, jint dst, jlong maskFmt,
2370N/A jintArray eltArray, jintArray glyphIDArray, jint eltCnt, jint glyphCnt) {
2370N/A jint i;
2370N/A jint *ids;
2370N/A jint *elts;
2370N/A XGlyphElt32 *xelts;
3818N/A unsigned int *xids;
2370N/A XGlyphElt32 selts[24];
3818N/A unsigned int sids[256];
2370N/A int charCnt = 0;
2370N/A
2370N/A if (eltCnt <= 24) {
2370N/A xelts = &selts[0];
2370N/A }else {
2370N/A xelts = (XGlyphElt32 *) malloc(sizeof(XGlyphElt32) * eltCnt);
3609N/A if (xelts == NULL) {
3609N/A return;
3609N/A }
2370N/A }
2370N/A
2370N/A if (glyphCnt <= 256) {
2370N/A xids = &sids[0];
3609N/A } else {
3818N/A xids = (unsigned int*)malloc(sizeof(unsigned int) * glyphCnt);
3609N/A if (xids == NULL) {
3609N/A if (xelts != &selts[0]) {
3609N/A free(xelts);
3609N/A }
3609N/A return;
3609N/A }
2370N/A }
2370N/A
3609N/A if ((ids = (jint *)
3609N/A (*env)->GetPrimitiveArrayCritical(env, glyphIDArray, NULL)) == NULL) {
3609N/A if (xelts != &selts[0]) {
3609N/A free(xelts);
3609N/A }
3609N/A if (xids != &sids[0]) {
3609N/A free(xids);
3609N/A }
3609N/A return;
2370N/A }
2370N/A if ((elts = (jint *)
2370N/A (*env)->GetPrimitiveArrayCritical(env, eltArray, NULL)) == NULL) {
2370N/A (*env)->ReleasePrimitiveArrayCritical(env,
2370N/A glyphIDArray, ids, JNI_ABORT);
3609N/A if (xelts != &selts[0]) {
3609N/A free(xelts);
3609N/A }
3609N/A if (xids != &sids[0]) {
3609N/A free(xids);
3609N/A }
3609N/A return;
2370N/A }
2370N/A
2370N/A for (i=0; i < glyphCnt; i++) {
3818N/A xids[i] = ids[i];
2370N/A }
2370N/A
2370N/A for (i=0; i < eltCnt; i++) {
2370N/A xelts[i].nchars = elts[i*4 + 0];
2370N/A xelts[i].xOff = elts[i*4 + 1];
2370N/A xelts[i].yOff = elts[i*4 + 2];
2370N/A xelts[i].glyphset = (GlyphSet) elts[i*4 + 3];
3818N/A xelts[i].chars = &xids[charCnt];
2370N/A
2370N/A charCnt += xelts[i].nchars;
2370N/A }
2370N/A
2370N/A XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst,
2370N/A (XRenderPictFormat *) jlong_to_ptr(maskFmt),
2370N/A 0, 0, 0, 0, xelts, eltCnt);
2370N/A
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT);
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT);
2370N/A
2370N/A if (xelts != &selts[0]) {
3609N/A free(xelts);
2370N/A }
2370N/A
2370N/A if (xids != &sids[0]) {
3609N/A free(xids);
2370N/A }
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_setGCMode
2370N/A (JNIEnv *env, jobject this, jlong gc, jboolean copy) {
2370N/A GC xgc = (GC) jlong_to_ptr(gc);
2370N/A
2370N/A if (copy == JNI_TRUE) {
2370N/A XSetFunction(awt_display, xgc, GXcopy);
2370N/A } else {
2370N/A XSetFunction(awt_display, xgc, GXxor);
2370N/A }
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_GCRectanglesNative
2370N/A (JNIEnv *env, jclass xsd, jint dst, jlong gc,
2370N/A jintArray rectArray, jint rectCnt) {
2370N/A int i;
2370N/A jint* rects;
2370N/A XRectangle *xRects;
2370N/A XRectangle sRects[256];
2370N/A
2370N/A if (rectCnt <= 256) {
2370N/A xRects = &sRects[0];
2370N/A } else {
2370N/A xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
2370N/A if (xRects == NULL) {
2370N/A return;
2370N/A }
2370N/A }
2370N/A
3609N/A if ((rects = (jint*)
3609N/A (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
3609N/A if (xRects != &sRects[0]) {
3609N/A free(xRects);
3609N/A }
3609N/A return;
2370N/A }
2370N/A
2370N/A for (i=0; i < rectCnt; i++) {
2370N/A xRects[i].x = rects[i*4 + 0];
2370N/A xRects[i].y = rects[i*4 + 1];
2370N/A xRects[i].width = rects[i*4 + 2];
2370N/A xRects[i].height = rects[i*4 + 3];
2370N/A }
2370N/A
2370N/A XFillRectangles(awt_display, (Drawable) dst, (GC) jlong_to_ptr(gc), xRects, rectCnt);
2370N/A
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
2370N/A if (xRects != &sRects[0]) {
2370N/A free(xRects);
2370N/A }
2370N/A}
2370N/A
2370N/AJNIEXPORT void JNICALL
2370N/AJava_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative
2370N/A (JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt,
2370N/A jint dst, jint srcX, jint srcY, jintArray trapArray) {
2370N/A jint *traps;
2370N/A
2370N/A if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) {
2370N/A return;
2370N/A }
2370N/A
2370N/A XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst,
2370N/A (XRenderPictFormat *) jlong_to_ptr(maskFmt),
2370N/A srcX, srcY, (XTrapezoid *) (traps+5), traps[0]);
2370N/A
2370N/A (*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT);
2370N/A}