Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c
32288 views
/*1* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "X11SurfaceData.h"26#include <jni.h>27#include <math.h>28#include "Region.h"29#include "fontscalerdefs.h"3031#include <X11/extensions/Xrender.h>3233#ifdef __linux__34#include <sys/utsname.h>35#endif3637/* On Solaris 10 updates 8, 9, the render.h file defines these38* protocol values but does not define the structs in Xrender.h.39* Thus in order to get these always defined on Solaris 1040* we will undefine the symbols if we have determined via the41* makefiles that Xrender.h is lacking the structs. This will42* trigger providing our own definitions as on earlier updates.43* We could assume that *all* Solaris 10 update versions will lack the updated44* Xrender.h and do this based solely on O/S being any 5.10 version, but this45* could still change and we'd be broken again as we'd be re-defining them.46*/47#ifdef SOLARIS10_NO_XRENDER_STRUCTS48#undef X_RenderCreateLinearGradient49#undef X_RenderCreateRadialGradient50#endif5152#ifndef X_RenderCreateLinearGradient53typedef struct _XLinearGradient {54XPointFixed p1;55XPointFixed p2;56} XLinearGradient;57#endif5859#ifndef X_RenderCreateRadialGradient60typedef struct _XCircle {61XFixed x;62XFixed y;63XFixed radius;64} XCircle;6566typedef struct _XRadialGradient {67XCircle inner;68XCircle outer;69} XRadialGradient;70#endif7172#include <dlfcn.h>7374#if defined(__solaris__) || defined(_AIX)75/* Solaris 10 and AIX will not have these symbols at runtime */7677typedef Picture (*XRenderCreateLinearGradientFuncType)78(Display *dpy,79const XLinearGradient *gradient,80const XFixed *stops,81const XRenderColor *colors,82int nstops);8384typedef Picture (*XRenderCreateRadialGradientFuncType)85(Display *dpy,86const XRadialGradient *gradient,87const XFixed *stops,88const XRenderColor *colors,89int nstops);9091static92XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;93static94XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;95#endif9697#define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \98{ \99TRANSFORM.matrix[0][0] = M00; \100TRANSFORM.matrix[0][1] = M01; \101TRANSFORM.matrix[0][2] = M02; \102TRANSFORM.matrix[1][0] = M10; \103TRANSFORM.matrix[1][1] = M11; \104TRANSFORM.matrix[1][2] = M12; \105TRANSFORM.matrix[2][0] = 0; \106TRANSFORM.matrix[2][1] = 0; \107TRANSFORM.matrix[2][2] = 1<<16; \108}109110/* The xrender pipleine requires libXrender.so version 0.9.3 or later. */111#define REQUIRED_XRENDER_VER1 0112#define REQUIRED_XRENDER_VER2 9113#define REQUIRED_XRENDER_VER3 3114115#define PKGINFO_LINE_LEN_MAX 256116#define PKGINFO_LINE_CNT_MAX 50117118/*119* X protocol uses (u_int16)length to specify the length in 4 bytes quantities120* of the whole request. Both XRenderFillRectangles() and XFillRectangles()121* have provisions to fragment into several requests if the number of rectangles122* plus the current x request does not fit into 65535*4 bytes. While123* XRenderCreateLinearGradient() and XRenderCreateRadialGradient() have124* provisions to gracefully degrade if the resulting request would exceed125* 65535*4 bytes.126*127* Below, we define a cap of 65535*4 bytes for the maximum X request payload128* allowed for Non-(XRenderFillRectangles() or XFillRectangles()) API calls,129* just to be conservative. This is offset by the size of our maximum x*Req130* type in this compilation unit, which is xRenderCreateRadiaGradientReq.131*132* Note that sizeof(xRenderCreateRadiaGradientReq) = 36133*/134#define MAX_PAYLOAD (262140u - 36u)135#define MAXUINT (0xffffffffu)136137static jboolean IsXRenderAvailable(jboolean verbose, jboolean ignoreLinuxVersion) {138139void *xrenderlib;140141int major_opcode, first_event, first_error;142jboolean available = JNI_TRUE;143144if (!XQueryExtension(awt_display, "RENDER",145&major_opcode, &first_event, &first_error)) {146return JNI_FALSE;147}148149#if defined(__solaris__) || defined(_AIX)150xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);151if (xrenderlib != NULL) {152153XRenderCreateLinearGradientFunc =154(XRenderCreateLinearGradientFuncType)155dlsym(xrenderlib, "XRenderCreateLinearGradient");156157XRenderCreateRadialGradientFunc =158(XRenderCreateRadialGradientFuncType)159dlsym(xrenderlib, "XRenderCreateRadialGradient");160161if (XRenderCreateLinearGradientFunc == NULL ||162XRenderCreateRadialGradientFunc == NULL)163{164available = JNI_FALSE;165}166dlclose(xrenderlib);167} else {168available = JNI_FALSE;169}170#else171Dl_info info;172jboolean versionInfoIsFound = JNI_FALSE;173174memset(&info, 0, sizeof(Dl_info));175if (dladdr(&XRenderChangePicture, &info) && info.dli_fname != NULL) {176char pkgInfoPath[FILENAME_MAX];177char *pkgFileName = "/pkgconfig/xrender.pc";178size_t pkgFileNameLen = strlen(pkgFileName);179size_t pos, len = strlen(info.dli_fname);180181pos = len;182while (pos > 0 && info.dli_fname[pos] != '/') {183pos -= 1;184}185186if (pos > 0 && pos < (FILENAME_MAX - pkgFileNameLen - 1)) {187struct stat stat_info;188189// compose absolute filename to package config190strncpy(pkgInfoPath, info.dli_fname, pos);191192strcpy(pkgInfoPath + pos, pkgFileName);193pkgInfoPath[pos + pkgFileNameLen] = '\0';194195// check whether the config file exist and is a regular file196if ((stat(pkgInfoPath, &stat_info)== 0) &&197S_ISREG(stat_info.st_mode))198{199FILE *fp = fopen(pkgInfoPath, "r");200if (fp != NULL) {201char line[PKGINFO_LINE_LEN_MAX];202int lineCount = PKGINFO_LINE_CNT_MAX;203char *versionPrefix = "Version: ";204size_t versionPrefixLen = strlen(versionPrefix);205206// look for version207while(fgets(line,sizeof(line),fp) != NULL && --lineCount > 0) {208size_t lineLen = strlen(line);209210if (lineLen > versionPrefixLen &&211strncmp(versionPrefix, line, versionPrefixLen) == 0)212{213int v1 = 0, v2 = 0, v3 = 0;214int numNeeded = 3,numProcessed;215char* version = line + versionPrefixLen;216numProcessed = sscanf(version, "%d.%d.%d", &v1, &v2, &v3);217218if (numProcessed == numNeeded) {219// we successfuly read the library version220versionInfoIsFound = JNI_TRUE;221222if (REQUIRED_XRENDER_VER1 == v1 &&223((REQUIRED_XRENDER_VER2 > v2) ||224((REQUIRED_XRENDER_VER2 == v2) && (REQUIRED_XRENDER_VER3 > v3))))225{226available = JNI_FALSE;227228if (verbose) {229printf("INFO: the version %d.%d.%d of libXrender.so is "230"not supported.\n\tSee release notes for more details.\n",231v1, v2, v3);232fflush(stdout);233}234} else {235if (verbose) {236printf("INFO: The version of libXrender.so "237"is detected as %d.%d%d\n", v1, v2, v3);238fflush(stdout);239}240}241}242break;243}244}245fclose(fp);246}247}248}249}250if (verbose && !versionInfoIsFound) {251printf("WARNING: The version of libXrender.so cannot be detected.\n,"252"The pipe line will be enabled, but note that versions less than 0.9.3\n"253"may cause hangs and crashes\n"254"\tSee the release notes for more details.\n");255fflush(stdout);256}257#endif258259#ifdef __linux__260/*261* Check for Linux >= 3.5 (Ubuntu 12.04.02 LTS) to avoid hitting262* https://bugs.freedesktop.org/show_bug.cgi?id=48045263*/264struct utsname utsbuf;265if(uname(&utsbuf) >= 0) {266int major, minor, revision;267if(sscanf(utsbuf.release, "%i.%i.%i", &major, &minor, &revision) == 3) {268if(major < 3 || (major == 3 && minor < 5)) {269if(!ignoreLinuxVersion) {270available = JNI_FALSE;271}272else if(verbose) {273printf("WARNING: Linux < 3.5 detected.\n"274"The pipeline will be enabled, but graphical "275"artifacts can occur with old graphic drivers.\n"276"See the release notes for more details.\n");277fflush(stdout);278}279}280}281}282#endif // __linux__283284return available;285}286/*287* Class: sun_awt_X11GraphicsEnvironment288* Method: initGLX289* Signature: ()Z290*/291JNIEXPORT jboolean JNICALL292Java_sun_awt_X11GraphicsEnvironment_initXRender293(JNIEnv *env, jclass x11ge, jboolean verbose, jboolean ignoreLinuxVersion)294{295#ifndef HEADLESS296static jboolean xrenderAvailable = JNI_FALSE;297static jboolean firstTime = JNI_TRUE;298299if (firstTime) {300#ifdef DISABLE_XRENDER_BY_DEFAULT301if (verbose == JNI_FALSE) {302xrenderAvailable = JNI_FALSE;303firstTime = JNI_FALSE;304return xrenderAvailable;305}306#endif307AWT_LOCK();308xrenderAvailable = IsXRenderAvailable(verbose, ignoreLinuxVersion);309AWT_UNLOCK();310firstTime = JNI_FALSE;311}312return xrenderAvailable;313#else314return JNI_FALSE;315#endif /* !HEADLESS */316}317318319JNIEXPORT void JNICALL320Java_sun_java2d_xr_XRBackendNative_initIDs(JNIEnv *env, jclass cls) {321char *maskData;322XImage* defaultImg;323jfieldID maskImgID;324jlong fmt8;325jlong fmt32;326327jfieldID a8ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_A8", "J");328if (a8ID == NULL) {329return;330}331jfieldID argb32ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_ARGB32", "J");332if (argb32ID == NULL) {333return;334}335336if (awt_display == (Display *)NULL) {337return;338}339340fmt8 = ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardA8));341fmt32 = ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardARGB32));342343(*env)->SetStaticLongField(env, cls, a8ID, fmt8);344(*env)->SetStaticLongField(env, cls, argb32ID, fmt32);345346maskData = (char *) malloc(32*32);347if (maskData == NULL) {348return;349}350351defaultImg = XCreateImage(awt_display, NULL, 8, ZPixmap, 0, maskData, 32, 32, 8, 0);352defaultImg->data = maskData; //required?353maskImgID = (*env)->GetStaticFieldID(env, cls, "MASK_XIMG", "J");354if (maskImgID == NULL) {355return;356}357358(*env)->SetStaticLongField(env, cls, maskImgID, ptr_to_jlong(defaultImg));359}360361JNIEXPORT void JNICALL362Java_sun_java2d_xr_XRBackendNative_freeGC363(JNIEnv *env, jobject this, jlong gc) {364XFreeGC(awt_display, (GC) jlong_to_ptr(gc));365}366367JNIEXPORT jlong JNICALL368Java_sun_java2d_xr_XRBackendNative_createGC369(JNIEnv *env, jobject this, jint drawable) {370GC xgc = XCreateGC(awt_display, (Drawable) drawable, 0L, NULL);371return ptr_to_jlong(xgc);372}373374JNIEXPORT jint JNICALL375Java_sun_java2d_xr_XRBackendNative_createPixmap(JNIEnv *env, jobject this,376jint drawable, jint depth,377jint width, jint height) {378return (jint) XCreatePixmap(awt_display, (Drawable) drawable,379width, height, depth);380}381382JNIEXPORT jint JNICALL383Java_sun_java2d_xr_XRBackendNative_createPictureNative384(JNIEnv *env, jclass cls, jint drawable, jlong formatPtr) {385XRenderPictureAttributes pict_attr;386return XRenderCreatePicture(awt_display, (Drawable) drawable,387(XRenderPictFormat *) jlong_to_ptr(formatPtr),3880, &pict_attr);389}390391JNIEXPORT void JNICALL392Java_sun_java2d_xr_XRBackendNative_freePicture393(JNIEnv *env, jobject this, jint picture) {394XRenderFreePicture(awt_display, (Picture) picture);395}396397JNIEXPORT void JNICALL398Java_sun_java2d_xr_XRBackendNative_freePixmap399(JNIEnv *env, jobject this, jint pixmap) {400XFreePixmap(awt_display, (Pixmap) pixmap);401}402403JNIEXPORT void JNICALL404Java_sun_java2d_xr_XRBackendNative_setPictureRepeat405(JNIEnv *env, jobject this, jint picture, jint repeat) {406XRenderPictureAttributes pict_attr;407pict_attr.repeat = repeat;408XRenderChangePicture (awt_display, (Picture) picture, CPRepeat, &pict_attr);409}410411412JNIEXPORT void JNICALL413Java_sun_java2d_xr_XRBackendNative_setGCExposures414(JNIEnv *env, jobject this, jlong gc, jboolean exposure) {415XSetGraphicsExposures(awt_display,416(GC) jlong_to_ptr(gc), exposure ? True : False); //TODO: ????417}418419JNIEXPORT void JNICALL420Java_sun_java2d_xr_XRBackendNative_setGCForeground421(JNIEnv *env, jobject this, jlong gc, jint pixel) {422XSetForeground(awt_display, (GC) jlong_to_ptr(gc), (unsigned long) pixel);423}424425426JNIEXPORT void JNICALL427Java_sun_java2d_xr_XRBackendNative_copyArea428(JNIEnv *env, jobject this, jint src, jint dst, jlong gc,429jint srcx, jint srcy, jint width, jint height, jint dstx, jint dsty) {430XCopyArea(awt_display, (Drawable) src, (Drawable) dst,431(GC) jlong_to_ptr(gc), srcx, srcy, width, height, dstx, dsty);432}433434JNIEXPORT void JNICALL435Java_sun_java2d_xr_XRBackendNative_renderComposite436(JNIEnv *env, jobject this, jbyte op, jint src, jint mask, jint dst,437jint srcX, jint srcY, jint maskX, jint maskY,438jint dstX, jint dstY, jint width, jint height) {439XRenderComposite (awt_display, op,440(Picture)src, (Picture)mask, (Picture)dst,441srcX, srcY, maskX, maskY, dstX, dstY, width, height);442}443444JNIEXPORT void JNICALL445Java_sun_java2d_xr_XRBackendNative_renderRectangle446(JNIEnv *env, jobject this, jint dst, jbyte op,447jshort red, jshort green, jshort blue, jshort alpha,448jint x, jint y, jint width, jint height) {449XRenderColor color;450color.alpha = alpha;451color.red = red;452color.green = green;453color.blue = blue;454XRenderFillRectangle(awt_display, op, (Picture) dst, &color,455x, y, width, height);456}457458JNIEXPORT void JNICALL459Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative460(JNIEnv *env, jclass xsd, jint dst, jbyte op,461jshort red, jshort green, jshort blue, jshort alpha,462jintArray rectArray, jint rectCnt) {463int i;464jint* rects;465XRectangle *xRects;466XRectangle sRects[256];467468XRenderColor color;469color.alpha = alpha;470color.red = red;471color.green = green;472color.blue = blue;473474if (rectCnt <= 256) {475xRects = &sRects[0];476} else {477if (MAXUINT / sizeof(XRectangle) < (unsigned)rectCnt) {478/* rectCnt too big, integer overflow */479return;480}481xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);482if (xRects == NULL) {483return;484}485}486487if ((rects = (jint *)488(*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {489if (xRects != &sRects[0]) {490free(xRects);491}492return;493}494495for (i=0; i < rectCnt; i++) {496xRects[i].x = rects[i*4 + 0];497xRects[i].y = rects[i*4 + 1];498xRects[i].width = rects[i*4 + 2];499xRects[i].height = rects[i*4 + 3];500}501502XRenderFillRectangles(awt_display, op,503(Picture) dst, &color, xRects, rectCnt);504505(*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);506if (xRects != &sRects[0]) {507free(xRects);508}509}510511JNIEXPORT void JNICALL512Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative513(JNIEnv *env, jclass xsd, jint pic,514jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {515516XTransform tr;517BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);518XRenderSetPictureTransform (awt_display, (Picture) pic, &tr);519}520521JNIEXPORT jint JNICALL522Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative523(JNIEnv *env, jclass xsd, jfloatArray fractionsArray,524jshortArray pixelsArray, jint x1, jint y1, jint x2, jint y2,525jint numStops, jint repeat) {526jint i;527jshort* pixels;528jfloat* fractions;529XRenderPictureAttributes pict_attr;530Picture gradient = 0;531XRenderColor *colors;532XFixed *stops;533XLinearGradient grad;534535if (MAX_PAYLOAD / (sizeof(XRenderColor) + sizeof(XFixed))536< (unsigned)numStops) {537/* numStops too big, payload overflow */538return -1;539}540541if ((pixels = (jshort *)542(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {543return -1;544}545if ((fractions = (jfloat *)546(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {547(*env)->ReleasePrimitiveArrayCritical(env,548pixelsArray, pixels, JNI_ABORT);549return -1;550}551552grad.p1.x = x1;553grad.p1.y = y1;554grad.p2.x = x2;555grad.p2.y = y2;556557/*TODO optimized & malloc check*/558colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));559stops = (XFixed *) malloc(numStops * sizeof(XFixed));560561if (colors == NULL || stops == NULL) {562if (colors != NULL) {563free(colors);564}565if (stops != NULL) {566free(stops);567}568(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);569(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);570return -1;571}572573for (i=0; i < numStops; i++) {574stops[i] = XDoubleToFixed(fractions[i]);575colors[i].alpha = pixels[i*4 + 0];576colors[i].red = pixels[i*4 + 1];577colors[i].green = pixels[i*4 + 2];578colors[i].blue = pixels[i*4 + 3];579}580#ifdef __solaris__581if (XRenderCreateLinearGradientFunc!=NULL) {582gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);583}584#else585gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);586#endif587free(colors);588free(stops);589590(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);591(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);592593if (gradient != 0) {594pict_attr.repeat = repeat;595XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);596}597598return (jint) gradient;599}600601602JNIEXPORT jint JNICALL603Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative604(JNIEnv *env, jclass xsd, jfloatArray fractionsArray,605jshortArray pixelsArray, jint numStops,606jint centerX, jint centerY,607jint innerRadius, jint outerRadius, jint repeat) {608jint i;609jshort* pixels;610jfloat* fractions;611XRenderPictureAttributes pict_attr;612Picture gradient = 0;613XRenderColor *colors;614XFixed *stops;615XRadialGradient grad;616617if (MAX_PAYLOAD / (sizeof(XRenderColor) + sizeof(XFixed))618< (unsigned)numStops) {619/* numStops too big, payload overflow */620return -1;621}622623if ((pixels =624(jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {625return -1;626}627if ((fractions = (jfloat *)628(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {629(*env)->ReleasePrimitiveArrayCritical(env,630pixelsArray, pixels, JNI_ABORT);631return -1; //TODO release pixels first632}633634grad.inner.x = centerX;635grad.inner.y = centerY;636grad.inner.radius = innerRadius;637grad.outer.x = centerX;638grad.outer.y = centerY;639grad.outer.radius = outerRadius;640641/*TODO optimized & malloc check*/642colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));643stops = (XFixed *) malloc(numStops * sizeof(XFixed));644645if (colors == NULL || stops == NULL) {646if (colors != NULL) {647free(colors);648}649if (stops != NULL) {650free(stops);651}652(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);653(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);654return -1;655}656657for (i=0; i < numStops; i++) {658stops[i] = XDoubleToFixed(fractions[i]);659colors[i].alpha = pixels[i*4 + 0];660colors[i].red = pixels[i*4 + 1];661colors[i].green = pixels[i*4 + 2];662colors[i].blue = pixels[i*4 + 3];663}664#ifdef __solaris__665if (XRenderCreateRadialGradientFunc != NULL) {666gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);667}668#else669gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);670#endif671free(colors);672free(stops);673674(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);675(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);676677678if (gradient != 0) {679pict_attr.repeat = repeat;680XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);681}682683return (jint) gradient;684}685686JNIEXPORT void JNICALL687Java_sun_java2d_xr_XRBackendNative_setFilter688(JNIEnv *env, jobject this, jint picture, jint filter) {689690char * filterName = "fast";691692switch(filter) {693case 0:694filterName = "fast";695break;696697case 1:698filterName = "good";699break;700701case 2:702filterName = "best";703break;704}705706XRenderSetPictureFilter(awt_display, (Picture) picture, filterName, NULL, 0);707}708709JNIEXPORT void JNICALL710Java_sun_java2d_xr_XRBackendNative_XRSetClipNative711(JNIEnv *env, jclass xsd, jlong dst,712jint x1, jint y1, jint x2, jint y2,713jobject complexclip, jboolean isGC)714{715int numrects;716XRectangle rects[256];717XRectangle *pRect = rects;718719numrects = RegionToYXBandedRectangles(env,720x1, y1, x2, y2, complexclip,721&pRect, 256);722723if (isGC == JNI_TRUE) {724if (dst != (jlong) 0) {725XSetClipRectangles(awt_display, (GC) jlong_to_ptr(dst), 0, 0, pRect, numrects, YXBanded);726}727} else {728XRenderSetPictureClipRectangles (awt_display, (Picture) dst, 0, 0, pRect, numrects);729}730731if (pRect != rects) {732free(pRect);733}734}735736JNIEXPORT void JNICALL737Java_sun_java2d_xr_XRBackendNative_putMaskNative738(JNIEnv *env, jclass cls, jint drawable, jlong gc, jbyteArray imageData,739jint sx, jint sy, jint dx, jint dy, jint width, jint height,740jint maskOff, jint maskScan, jfloat ea, jlong imgPtr) {741742int line, pix;743char *mask;744char *defaultData;745XImage *defaultImg, *img;746jboolean imageFits;747748if ((mask = (char *)749(*env)->GetPrimitiveArrayCritical(env, imageData, NULL)) == NULL) {750return;751}752753defaultImg = (XImage *) jlong_to_ptr(imgPtr);754755if (ea != 1.0f) {756for (line=0; line < height; line++) {757for (pix=0; pix < width; pix++) {758size_t index = (size_t) maskScan * line + pix + maskOff;759mask[index] = (((unsigned char) mask[index])*ea);760}761}762}763764/*765* 1. If existing XImage and supplied buffer match, only adjust the data pointer766* 2. If existing XImage is large enough to hold the data but does not match in767* scan the data is copied to fit the XImage.768* 3. If data is larger than the existing XImage a new temporary XImage is769* allocated.770* The default XImage is optimized for the AA tiles, which are currently 32x32.771*/772defaultData = defaultImg->data;773img = defaultImg;774imageFits = defaultImg->width >= width && defaultImg->height >= height;775776if (imageFits &&777maskOff == defaultImg->xoffset && maskScan == defaultImg->bytes_per_line) {778defaultImg->data = mask;779} else {780if (imageFits) {781for (line=0; line < height; line++) {782for (pix=0; pix < width; pix++) {783img->data[(size_t) line * img->bytes_per_line + pix] =784(unsigned char) (mask[(size_t) maskScan * line + pix + maskOff]);785}786}787} else {788img = XCreateImage(awt_display, NULL, 8, ZPixmap,789maskOff, mask, maskScan, height, 8, 0);790}791}792793XPutImage(awt_display, (Pixmap) drawable, (GC) jlong_to_ptr(gc),794img, 0, 0, 0, 0, width, height);795(*env)->ReleasePrimitiveArrayCritical(env, imageData, mask, JNI_ABORT);796797if (img != defaultImg) {798img->data = NULL;799XDestroyImage(img);800}801defaultImg->data = defaultData;802}803804JNIEXPORT void JNICALL805Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative806(JNIEnv *env, jclass cls, jint glyphSet,807jlongArray glyphInfoPtrsArray, jint glyphCnt,808jbyteArray pixelDataArray, int pixelDataLength) {809jlong *glyphInfoPtrs;810unsigned char *pixelData;811int i;812813if (MAX_PAYLOAD / (sizeof(XGlyphInfo) + sizeof(Glyph))814< (unsigned)glyphCnt) {815/* glyphCnt too big, payload overflow */816return;817}818819XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt);820Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);821822if (xginfo == NULL || gid == NULL) {823if (xginfo != NULL) {824free(xginfo);825}826if (gid != NULL) {827free(gid);828}829return;830}831832if ((glyphInfoPtrs = (jlong *)(*env)->833GetPrimitiveArrayCritical(env, glyphInfoPtrsArray, NULL)) == NULL)834{835free(xginfo);836free(gid);837return;838}839840if ((pixelData = (unsigned char *)841(*env)->GetPrimitiveArrayCritical(env, pixelDataArray, NULL)) == NULL)842{843(*env)->ReleasePrimitiveArrayCritical(env,844glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);845free(xginfo);846free(gid);847return;848}849850for (i=0; i < glyphCnt; i++) {851GlyphInfo *jginfo = (GlyphInfo *) jlong_to_ptr(glyphInfoPtrs[i]);852853// 'jginfo->cellInfo' is of type 'void*'854// (see definition of 'GlyphInfo' in fontscalerdefs.h)855// 'Glyph' is typedefed to 'unsigned long'856// (see http://www.x.org/releases/X11R7.7/doc/libXrender/libXrender.txt)857// Maybe we should assert that (sizeof(void*) == sizeof(Glyph)) ?858gid[i] = (Glyph) (jginfo->cellInfo);859xginfo[i].x = (-jginfo->topLeftX);860xginfo[i].y = (-jginfo->topLeftY);861xginfo[i].width = jginfo->width;862xginfo[i].height = jginfo->height;863xginfo[i].xOff = round(jginfo->advanceX);864xginfo[i].yOff = round(jginfo->advanceY);865}866867XRenderAddGlyphs(awt_display, glyphSet, &gid[0], &xginfo[0], glyphCnt,868(const char*)pixelData, pixelDataLength);869870(*env)->ReleasePrimitiveArrayCritical(env, glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);871(*env)->ReleasePrimitiveArrayCritical(env, pixelDataArray, pixelData, JNI_ABORT);872873free(xginfo);874free(gid);875}876877JNIEXPORT void JNICALL878Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative879(JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) {880881if (MAX_PAYLOAD / sizeof(Glyph) < (unsigned)glyphCnt) {882/* glyphCnt too big, payload overflow */883return;884}885886/* The glyph ids are 32 bit but may be stored in a 64 bit long on887* a 64 bit architecture. So optimise the 32 bit case to avoid888* extra stack or heap allocations by directly referencing the889* underlying Java array and only allocate on 64 bit.890*/891if (sizeof(jint) == sizeof(Glyph)) {892jint *gids =893(*env)->GetPrimitiveArrayCritical(env, gidArray, NULL);894if (gids == NULL) {895return;896} else {897XRenderFreeGlyphs(awt_display,898(GlyphSet)glyphSet, (Glyph *)gids, glyphCnt);899(*env)->ReleasePrimitiveArrayCritical(env, gidArray,900gids, JNI_ABORT);901}902return;903} else {904Glyph stack_ids[64];905Glyph *gids = NULL;906jint* jgids = NULL;907int i;908909if (glyphCnt <= 64) {910gids = stack_ids;911} else {912gids = (Glyph *)malloc(sizeof(Glyph) * glyphCnt);913if (gids == NULL) {914return;915}916}917jgids = (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL);918if (jgids == NULL) {919if (gids != stack_ids) {920free(gids);921}922return;923}924for (i=0; i < glyphCnt; i++) {925gids[i] = jgids[i];926}927XRenderFreeGlyphs(awt_display,928(GlyphSet) glyphSet, gids, glyphCnt);929(*env)->ReleasePrimitiveArrayCritical(env, gidArray,930jgids, JNI_ABORT);931if (gids != stack_ids) {932free(gids);933}934}935}936937JNIEXPORT jint JNICALL938Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative939(JNIEnv *env, jclass cls, jlong format) {940return XRenderCreateGlyphSet(awt_display, (XRenderPictFormat *) jlong_to_ptr(format));941}942943JNIEXPORT void JNICALL944Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative945(JNIEnv *env, jclass cls, jint op, jint src, jint dst,946jint sx, jint sy, jlong maskFmt, jintArray eltArray,947jintArray glyphIDArray, jint eltCnt, jint glyphCnt) {948jint i;949jint *ids;950jint *elts;951XGlyphElt32 *xelts;952unsigned int *xids;953XGlyphElt32 selts[24];954unsigned int sids[256];955int charCnt = 0;956957if ((MAX_PAYLOAD / sizeof(XGlyphElt32) < (unsigned)eltCnt)958|| (MAX_PAYLOAD / sizeof(unsigned int) < (unsigned)glyphCnt)959|| ((MAX_PAYLOAD - sizeof(XGlyphElt32)*(unsigned)eltCnt) /960sizeof(unsigned int) < (unsigned)glyphCnt))961{962/* (eltCnt, glyphCnt) too big, payload overflow */963return;964}965966if (eltCnt <= 24) {967xelts = &selts[0];968}else {969xelts = (XGlyphElt32 *) malloc(sizeof(XGlyphElt32) * eltCnt);970if (xelts == NULL) {971return;972}973}974975if (glyphCnt <= 256) {976xids = &sids[0];977} else {978xids = (unsigned int*)malloc(sizeof(unsigned int) * glyphCnt);979if (xids == NULL) {980if (xelts != &selts[0]) {981free(xelts);982}983return;984}985}986987if ((ids = (jint *)988(*env)->GetPrimitiveArrayCritical(env, glyphIDArray, NULL)) == NULL) {989if (xelts != &selts[0]) {990free(xelts);991}992if (xids != &sids[0]) {993free(xids);994}995return;996}997if ((elts = (jint *)998(*env)->GetPrimitiveArrayCritical(env, eltArray, NULL)) == NULL) {999(*env)->ReleasePrimitiveArrayCritical(env,1000glyphIDArray, ids, JNI_ABORT);1001if (xelts != &selts[0]) {1002free(xelts);1003}1004if (xids != &sids[0]) {1005free(xids);1006}1007return;1008}10091010for (i=0; i < glyphCnt; i++) {1011xids[i] = ids[i];1012}10131014for (i=0; i < eltCnt; i++) {1015xelts[i].nchars = elts[i*4 + 0];1016xelts[i].xOff = elts[i*4 + 1];1017xelts[i].yOff = elts[i*4 + 2];1018xelts[i].glyphset = (GlyphSet) elts[i*4 + 3];1019xelts[i].chars = &xids[charCnt];10201021charCnt += xelts[i].nchars;1022}10231024XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst,1025(XRenderPictFormat *) jlong_to_ptr(maskFmt),1026sx, sy, 0, 0, xelts, eltCnt);10271028(*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT);1029(*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT);10301031if (xelts != &selts[0]) {1032free(xelts);1033}10341035if (xids != &sids[0]) {1036free(xids);1037}1038}10391040JNIEXPORT void JNICALL1041Java_sun_java2d_xr_XRBackendNative_setGCMode1042(JNIEnv *env, jobject this, jlong gc, jboolean copy) {1043GC xgc = (GC) jlong_to_ptr(gc);10441045if (copy == JNI_TRUE) {1046XSetFunction(awt_display, xgc, GXcopy);1047} else {1048XSetFunction(awt_display, xgc, GXxor);1049}1050}10511052JNIEXPORT void JNICALL1053Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative1054(JNIEnv *env, jclass xsd, jint dst, jlong gc,1055jintArray rectArray, jint rectCnt) {1056int i;1057jint* rects;1058XRectangle *xRects;1059XRectangle sRects[256];10601061if (rectCnt <= 256) {1062xRects = &sRects[0];1063} else {1064if (MAXUINT / sizeof(XRectangle) < (unsigned)rectCnt) {1065/* rectCnt too big, integer overflow */1066return;1067}10681069xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);1070if (xRects == NULL) {1071return;1072}1073}10741075if ((rects = (jint*)1076(*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {1077if (xRects != &sRects[0]) {1078free(xRects);1079}1080return;1081}10821083for (i=0; i < rectCnt; i++) {1084xRects[i].x = rects[i*4 + 0];1085xRects[i].y = rects[i*4 + 1];1086xRects[i].width = rects[i*4 + 2];1087xRects[i].height = rects[i*4 + 3];1088}10891090XFillRectangles(awt_display, (Drawable) dst, (GC) jlong_to_ptr(gc), xRects, rectCnt);10911092(*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);1093if (xRects != &sRects[0]) {1094free(xRects);1095}1096}10971098JNIEXPORT void JNICALL1099Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative1100(JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt,1101jint dst, jint srcX, jint srcY, jintArray trapArray) {1102jint *traps;11031104if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) {1105return;1106}11071108XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst,1109(XRenderPictFormat *) jlong_to_ptr(maskFmt),1110srcX, srcY, (XTrapezoid *) (traps+5), traps[0]);11111112(*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT);1113}111411151116