Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c
32288 views
1
/*
2
* Copyright (c) 2010, 2013, 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
#ifdef __linux__
35
#include <sys/utsname.h>
36
#endif
37
38
/* On Solaris 10 updates 8, 9, the render.h file defines these
39
* protocol values but does not define the structs in Xrender.h.
40
* Thus in order to get these always defined on Solaris 10
41
* we will undefine the symbols if we have determined via the
42
* makefiles that Xrender.h is lacking the structs. This will
43
* trigger providing our own definitions as on earlier updates.
44
* We could assume that *all* Solaris 10 update versions will lack the updated
45
* Xrender.h and do this based solely on O/S being any 5.10 version, but this
46
* could still change and we'd be broken again as we'd be re-defining them.
47
*/
48
#ifdef SOLARIS10_NO_XRENDER_STRUCTS
49
#undef X_RenderCreateLinearGradient
50
#undef X_RenderCreateRadialGradient
51
#endif
52
53
#ifndef X_RenderCreateLinearGradient
54
typedef struct _XLinearGradient {
55
XPointFixed p1;
56
XPointFixed p2;
57
} XLinearGradient;
58
#endif
59
60
#ifndef X_RenderCreateRadialGradient
61
typedef struct _XCircle {
62
XFixed x;
63
XFixed y;
64
XFixed radius;
65
} XCircle;
66
67
typedef struct _XRadialGradient {
68
XCircle inner;
69
XCircle outer;
70
} XRadialGradient;
71
#endif
72
73
#include <dlfcn.h>
74
75
#if defined(__solaris__) || defined(_AIX)
76
/* Solaris 10 and AIX will not have these symbols at runtime */
77
78
typedef Picture (*XRenderCreateLinearGradientFuncType)
79
(Display *dpy,
80
const XLinearGradient *gradient,
81
const XFixed *stops,
82
const XRenderColor *colors,
83
int nstops);
84
85
typedef Picture (*XRenderCreateRadialGradientFuncType)
86
(Display *dpy,
87
const XRadialGradient *gradient,
88
const XFixed *stops,
89
const XRenderColor *colors,
90
int nstops);
91
92
static
93
XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;
94
static
95
XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;
96
#endif
97
98
#define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \
99
{ \
100
TRANSFORM.matrix[0][0] = M00; \
101
TRANSFORM.matrix[0][1] = M01; \
102
TRANSFORM.matrix[0][2] = M02; \
103
TRANSFORM.matrix[1][0] = M10; \
104
TRANSFORM.matrix[1][1] = M11; \
105
TRANSFORM.matrix[1][2] = M12; \
106
TRANSFORM.matrix[2][0] = 0; \
107
TRANSFORM.matrix[2][1] = 0; \
108
TRANSFORM.matrix[2][2] = 1<<16; \
109
}
110
111
/* The xrender pipleine requires libXrender.so version 0.9.3 or later. */
112
#define REQUIRED_XRENDER_VER1 0
113
#define REQUIRED_XRENDER_VER2 9
114
#define REQUIRED_XRENDER_VER3 3
115
116
#define PKGINFO_LINE_LEN_MAX 256
117
#define PKGINFO_LINE_CNT_MAX 50
118
119
/*
120
* X protocol uses (u_int16)length to specify the length in 4 bytes quantities
121
* of the whole request. Both XRenderFillRectangles() and XFillRectangles()
122
* have provisions to fragment into several requests if the number of rectangles
123
* plus the current x request does not fit into 65535*4 bytes. While
124
* XRenderCreateLinearGradient() and XRenderCreateRadialGradient() have
125
* provisions to gracefully degrade if the resulting request would exceed
126
* 65535*4 bytes.
127
*
128
* Below, we define a cap of 65535*4 bytes for the maximum X request payload
129
* allowed for Non-(XRenderFillRectangles() or XFillRectangles()) API calls,
130
* just to be conservative. This is offset by the size of our maximum x*Req
131
* type in this compilation unit, which is xRenderCreateRadiaGradientReq.
132
*
133
* Note that sizeof(xRenderCreateRadiaGradientReq) = 36
134
*/
135
#define MAX_PAYLOAD (262140u - 36u)
136
#define MAXUINT (0xffffffffu)
137
138
static jboolean IsXRenderAvailable(jboolean verbose, jboolean ignoreLinuxVersion) {
139
140
void *xrenderlib;
141
142
int major_opcode, first_event, first_error;
143
jboolean available = JNI_TRUE;
144
145
if (!XQueryExtension(awt_display, "RENDER",
146
&major_opcode, &first_event, &first_error)) {
147
return JNI_FALSE;
148
}
149
150
#if defined(__solaris__) || defined(_AIX)
151
xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
152
if (xrenderlib != NULL) {
153
154
XRenderCreateLinearGradientFunc =
155
(XRenderCreateLinearGradientFuncType)
156
dlsym(xrenderlib, "XRenderCreateLinearGradient");
157
158
XRenderCreateRadialGradientFunc =
159
(XRenderCreateRadialGradientFuncType)
160
dlsym(xrenderlib, "XRenderCreateRadialGradient");
161
162
if (XRenderCreateLinearGradientFunc == NULL ||
163
XRenderCreateRadialGradientFunc == NULL)
164
{
165
available = JNI_FALSE;
166
}
167
dlclose(xrenderlib);
168
} else {
169
available = JNI_FALSE;
170
}
171
#else
172
Dl_info info;
173
jboolean versionInfoIsFound = JNI_FALSE;
174
175
memset(&info, 0, sizeof(Dl_info));
176
if (dladdr(&XRenderChangePicture, &info) && info.dli_fname != NULL) {
177
char pkgInfoPath[FILENAME_MAX];
178
char *pkgFileName = "/pkgconfig/xrender.pc";
179
size_t pkgFileNameLen = strlen(pkgFileName);
180
size_t pos, len = strlen(info.dli_fname);
181
182
pos = len;
183
while (pos > 0 && info.dli_fname[pos] != '/') {
184
pos -= 1;
185
}
186
187
if (pos > 0 && pos < (FILENAME_MAX - pkgFileNameLen - 1)) {
188
struct stat stat_info;
189
190
// compose absolute filename to package config
191
strncpy(pkgInfoPath, info.dli_fname, pos);
192
193
strcpy(pkgInfoPath + pos, pkgFileName);
194
pkgInfoPath[pos + pkgFileNameLen] = '\0';
195
196
// check whether the config file exist and is a regular file
197
if ((stat(pkgInfoPath, &stat_info)== 0) &&
198
S_ISREG(stat_info.st_mode))
199
{
200
FILE *fp = fopen(pkgInfoPath, "r");
201
if (fp != NULL) {
202
char line[PKGINFO_LINE_LEN_MAX];
203
int lineCount = PKGINFO_LINE_CNT_MAX;
204
char *versionPrefix = "Version: ";
205
size_t versionPrefixLen = strlen(versionPrefix);
206
207
// look for version
208
while(fgets(line,sizeof(line),fp) != NULL && --lineCount > 0) {
209
size_t lineLen = strlen(line);
210
211
if (lineLen > versionPrefixLen &&
212
strncmp(versionPrefix, line, versionPrefixLen) == 0)
213
{
214
int v1 = 0, v2 = 0, v3 = 0;
215
int numNeeded = 3,numProcessed;
216
char* version = line + versionPrefixLen;
217
numProcessed = sscanf(version, "%d.%d.%d", &v1, &v2, &v3);
218
219
if (numProcessed == numNeeded) {
220
// we successfuly read the library version
221
versionInfoIsFound = JNI_TRUE;
222
223
if (REQUIRED_XRENDER_VER1 == v1 &&
224
((REQUIRED_XRENDER_VER2 > v2) ||
225
((REQUIRED_XRENDER_VER2 == v2) && (REQUIRED_XRENDER_VER3 > v3))))
226
{
227
available = JNI_FALSE;
228
229
if (verbose) {
230
printf("INFO: the version %d.%d.%d of libXrender.so is "
231
"not supported.\n\tSee release notes for more details.\n",
232
v1, v2, v3);
233
fflush(stdout);
234
}
235
} else {
236
if (verbose) {
237
printf("INFO: The version of libXrender.so "
238
"is detected as %d.%d%d\n", v1, v2, v3);
239
fflush(stdout);
240
}
241
}
242
}
243
break;
244
}
245
}
246
fclose(fp);
247
}
248
}
249
}
250
}
251
if (verbose && !versionInfoIsFound) {
252
printf("WARNING: The version of libXrender.so cannot be detected.\n,"
253
"The pipe line will be enabled, but note that versions less than 0.9.3\n"
254
"may cause hangs and crashes\n"
255
"\tSee the release notes for more details.\n");
256
fflush(stdout);
257
}
258
#endif
259
260
#ifdef __linux__
261
/*
262
* Check for Linux >= 3.5 (Ubuntu 12.04.02 LTS) to avoid hitting
263
* https://bugs.freedesktop.org/show_bug.cgi?id=48045
264
*/
265
struct utsname utsbuf;
266
if(uname(&utsbuf) >= 0) {
267
int major, minor, revision;
268
if(sscanf(utsbuf.release, "%i.%i.%i", &major, &minor, &revision) == 3) {
269
if(major < 3 || (major == 3 && minor < 5)) {
270
if(!ignoreLinuxVersion) {
271
available = JNI_FALSE;
272
}
273
else if(verbose) {
274
printf("WARNING: Linux < 3.5 detected.\n"
275
"The pipeline will be enabled, but graphical "
276
"artifacts can occur with old graphic drivers.\n"
277
"See the release notes for more details.\n");
278
fflush(stdout);
279
}
280
}
281
}
282
}
283
#endif // __linux__
284
285
return available;
286
}
287
/*
288
* Class: sun_awt_X11GraphicsEnvironment
289
* Method: initGLX
290
* Signature: ()Z
291
*/
292
JNIEXPORT jboolean JNICALL
293
Java_sun_awt_X11GraphicsEnvironment_initXRender
294
(JNIEnv *env, jclass x11ge, jboolean verbose, jboolean ignoreLinuxVersion)
295
{
296
#ifndef HEADLESS
297
static jboolean xrenderAvailable = JNI_FALSE;
298
static jboolean firstTime = JNI_TRUE;
299
300
if (firstTime) {
301
#ifdef DISABLE_XRENDER_BY_DEFAULT
302
if (verbose == JNI_FALSE) {
303
xrenderAvailable = JNI_FALSE;
304
firstTime = JNI_FALSE;
305
return xrenderAvailable;
306
}
307
#endif
308
AWT_LOCK();
309
xrenderAvailable = IsXRenderAvailable(verbose, ignoreLinuxVersion);
310
AWT_UNLOCK();
311
firstTime = JNI_FALSE;
312
}
313
return xrenderAvailable;
314
#else
315
return JNI_FALSE;
316
#endif /* !HEADLESS */
317
}
318
319
320
JNIEXPORT void JNICALL
321
Java_sun_java2d_xr_XRBackendNative_initIDs(JNIEnv *env, jclass cls) {
322
char *maskData;
323
XImage* defaultImg;
324
jfieldID maskImgID;
325
jlong fmt8;
326
jlong fmt32;
327
328
jfieldID a8ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_A8", "J");
329
if (a8ID == NULL) {
330
return;
331
}
332
jfieldID argb32ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_ARGB32", "J");
333
if (argb32ID == NULL) {
334
return;
335
}
336
337
if (awt_display == (Display *)NULL) {
338
return;
339
}
340
341
fmt8 = ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardA8));
342
fmt32 = ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardARGB32));
343
344
(*env)->SetStaticLongField(env, cls, a8ID, fmt8);
345
(*env)->SetStaticLongField(env, cls, argb32ID, fmt32);
346
347
maskData = (char *) malloc(32*32);
348
if (maskData == NULL) {
349
return;
350
}
351
352
defaultImg = XCreateImage(awt_display, NULL, 8, ZPixmap, 0, maskData, 32, 32, 8, 0);
353
defaultImg->data = maskData; //required?
354
maskImgID = (*env)->GetStaticFieldID(env, cls, "MASK_XIMG", "J");
355
if (maskImgID == NULL) {
356
return;
357
}
358
359
(*env)->SetStaticLongField(env, cls, maskImgID, ptr_to_jlong(defaultImg));
360
}
361
362
JNIEXPORT void JNICALL
363
Java_sun_java2d_xr_XRBackendNative_freeGC
364
(JNIEnv *env, jobject this, jlong gc) {
365
XFreeGC(awt_display, (GC) jlong_to_ptr(gc));
366
}
367
368
JNIEXPORT jlong JNICALL
369
Java_sun_java2d_xr_XRBackendNative_createGC
370
(JNIEnv *env, jobject this, jint drawable) {
371
GC xgc = XCreateGC(awt_display, (Drawable) drawable, 0L, NULL);
372
return ptr_to_jlong(xgc);
373
}
374
375
JNIEXPORT jint JNICALL
376
Java_sun_java2d_xr_XRBackendNative_createPixmap(JNIEnv *env, jobject this,
377
jint drawable, jint depth,
378
jint width, jint height) {
379
return (jint) XCreatePixmap(awt_display, (Drawable) drawable,
380
width, height, depth);
381
}
382
383
JNIEXPORT jint JNICALL
384
Java_sun_java2d_xr_XRBackendNative_createPictureNative
385
(JNIEnv *env, jclass cls, jint drawable, jlong formatPtr) {
386
XRenderPictureAttributes pict_attr;
387
return XRenderCreatePicture(awt_display, (Drawable) drawable,
388
(XRenderPictFormat *) jlong_to_ptr(formatPtr),
389
0, &pict_attr);
390
}
391
392
JNIEXPORT void JNICALL
393
Java_sun_java2d_xr_XRBackendNative_freePicture
394
(JNIEnv *env, jobject this, jint picture) {
395
XRenderFreePicture(awt_display, (Picture) picture);
396
}
397
398
JNIEXPORT void JNICALL
399
Java_sun_java2d_xr_XRBackendNative_freePixmap
400
(JNIEnv *env, jobject this, jint pixmap) {
401
XFreePixmap(awt_display, (Pixmap) pixmap);
402
}
403
404
JNIEXPORT void JNICALL
405
Java_sun_java2d_xr_XRBackendNative_setPictureRepeat
406
(JNIEnv *env, jobject this, jint picture, jint repeat) {
407
XRenderPictureAttributes pict_attr;
408
pict_attr.repeat = repeat;
409
XRenderChangePicture (awt_display, (Picture) picture, CPRepeat, &pict_attr);
410
}
411
412
413
JNIEXPORT void JNICALL
414
Java_sun_java2d_xr_XRBackendNative_setGCExposures
415
(JNIEnv *env, jobject this, jlong gc, jboolean exposure) {
416
XSetGraphicsExposures(awt_display,
417
(GC) jlong_to_ptr(gc), exposure ? True : False); //TODO: ????
418
}
419
420
JNIEXPORT void JNICALL
421
Java_sun_java2d_xr_XRBackendNative_setGCForeground
422
(JNIEnv *env, jobject this, jlong gc, jint pixel) {
423
XSetForeground(awt_display, (GC) jlong_to_ptr(gc), (unsigned long) pixel);
424
}
425
426
427
JNIEXPORT void JNICALL
428
Java_sun_java2d_xr_XRBackendNative_copyArea
429
(JNIEnv *env, jobject this, jint src, jint dst, jlong gc,
430
jint srcx, jint srcy, jint width, jint height, jint dstx, jint dsty) {
431
XCopyArea(awt_display, (Drawable) src, (Drawable) dst,
432
(GC) jlong_to_ptr(gc), srcx, srcy, width, height, dstx, dsty);
433
}
434
435
JNIEXPORT void JNICALL
436
Java_sun_java2d_xr_XRBackendNative_renderComposite
437
(JNIEnv *env, jobject this, jbyte op, jint src, jint mask, jint dst,
438
jint srcX, jint srcY, jint maskX, jint maskY,
439
jint dstX, jint dstY, jint width, jint height) {
440
XRenderComposite (awt_display, op,
441
(Picture)src, (Picture)mask, (Picture)dst,
442
srcX, srcY, maskX, maskY, dstX, dstY, width, height);
443
}
444
445
JNIEXPORT void JNICALL
446
Java_sun_java2d_xr_XRBackendNative_renderRectangle
447
(JNIEnv *env, jobject this, jint dst, jbyte op,
448
jshort red, jshort green, jshort blue, jshort alpha,
449
jint x, jint y, jint width, jint height) {
450
XRenderColor color;
451
color.alpha = alpha;
452
color.red = red;
453
color.green = green;
454
color.blue = blue;
455
XRenderFillRectangle(awt_display, op, (Picture) dst, &color,
456
x, y, width, height);
457
}
458
459
JNIEXPORT void JNICALL
460
Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative
461
(JNIEnv *env, jclass xsd, jint dst, jbyte op,
462
jshort red, jshort green, jshort blue, jshort alpha,
463
jintArray rectArray, jint rectCnt) {
464
int i;
465
jint* rects;
466
XRectangle *xRects;
467
XRectangle sRects[256];
468
469
XRenderColor color;
470
color.alpha = alpha;
471
color.red = red;
472
color.green = green;
473
color.blue = blue;
474
475
if (rectCnt <= 256) {
476
xRects = &sRects[0];
477
} else {
478
if (MAXUINT / sizeof(XRectangle) < (unsigned)rectCnt) {
479
/* rectCnt too big, integer overflow */
480
return;
481
}
482
xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
483
if (xRects == NULL) {
484
return;
485
}
486
}
487
488
if ((rects = (jint *)
489
(*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
490
if (xRects != &sRects[0]) {
491
free(xRects);
492
}
493
return;
494
}
495
496
for (i=0; i < rectCnt; i++) {
497
xRects[i].x = rects[i*4 + 0];
498
xRects[i].y = rects[i*4 + 1];
499
xRects[i].width = rects[i*4 + 2];
500
xRects[i].height = rects[i*4 + 3];
501
}
502
503
XRenderFillRectangles(awt_display, op,
504
(Picture) dst, &color, xRects, rectCnt);
505
506
(*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
507
if (xRects != &sRects[0]) {
508
free(xRects);
509
}
510
}
511
512
JNIEXPORT void JNICALL
513
Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative
514
(JNIEnv *env, jclass xsd, jint pic,
515
jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
516
517
XTransform tr;
518
BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
519
XRenderSetPictureTransform (awt_display, (Picture) pic, &tr);
520
}
521
522
JNIEXPORT jint JNICALL
523
Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative
524
(JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
525
jshortArray pixelsArray, jint x1, jint y1, jint x2, jint y2,
526
jint numStops, jint repeat) {
527
jint i;
528
jshort* pixels;
529
jfloat* fractions;
530
XRenderPictureAttributes pict_attr;
531
Picture gradient = 0;
532
XRenderColor *colors;
533
XFixed *stops;
534
XLinearGradient grad;
535
536
if (MAX_PAYLOAD / (sizeof(XRenderColor) + sizeof(XFixed))
537
< (unsigned)numStops) {
538
/* numStops too big, payload overflow */
539
return -1;
540
}
541
542
if ((pixels = (jshort *)
543
(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
544
return -1;
545
}
546
if ((fractions = (jfloat *)
547
(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
548
(*env)->ReleasePrimitiveArrayCritical(env,
549
pixelsArray, pixels, JNI_ABORT);
550
return -1;
551
}
552
553
grad.p1.x = x1;
554
grad.p1.y = y1;
555
grad.p2.x = x2;
556
grad.p2.y = y2;
557
558
/*TODO optimized & malloc check*/
559
colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
560
stops = (XFixed *) malloc(numStops * sizeof(XFixed));
561
562
if (colors == NULL || stops == NULL) {
563
if (colors != NULL) {
564
free(colors);
565
}
566
if (stops != NULL) {
567
free(stops);
568
}
569
(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
570
(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
571
return -1;
572
}
573
574
for (i=0; i < numStops; i++) {
575
stops[i] = XDoubleToFixed(fractions[i]);
576
colors[i].alpha = pixels[i*4 + 0];
577
colors[i].red = pixels[i*4 + 1];
578
colors[i].green = pixels[i*4 + 2];
579
colors[i].blue = pixels[i*4 + 3];
580
}
581
#ifdef __solaris__
582
if (XRenderCreateLinearGradientFunc!=NULL) {
583
gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);
584
}
585
#else
586
gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);
587
#endif
588
free(colors);
589
free(stops);
590
591
(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
592
(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
593
594
if (gradient != 0) {
595
pict_attr.repeat = repeat;
596
XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
597
}
598
599
return (jint) gradient;
600
}
601
602
603
JNIEXPORT jint JNICALL
604
Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative
605
(JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
606
jshortArray pixelsArray, jint numStops,
607
jint centerX, jint centerY,
608
jint innerRadius, jint outerRadius, jint repeat) {
609
jint i;
610
jshort* pixels;
611
jfloat* fractions;
612
XRenderPictureAttributes pict_attr;
613
Picture gradient = 0;
614
XRenderColor *colors;
615
XFixed *stops;
616
XRadialGradient grad;
617
618
if (MAX_PAYLOAD / (sizeof(XRenderColor) + sizeof(XFixed))
619
< (unsigned)numStops) {
620
/* numStops too big, payload overflow */
621
return -1;
622
}
623
624
if ((pixels =
625
(jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
626
return -1;
627
}
628
if ((fractions = (jfloat *)
629
(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
630
(*env)->ReleasePrimitiveArrayCritical(env,
631
pixelsArray, pixels, JNI_ABORT);
632
return -1; //TODO release pixels first
633
}
634
635
grad.inner.x = centerX;
636
grad.inner.y = centerY;
637
grad.inner.radius = innerRadius;
638
grad.outer.x = centerX;
639
grad.outer.y = centerY;
640
grad.outer.radius = outerRadius;
641
642
/*TODO optimized & malloc check*/
643
colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
644
stops = (XFixed *) malloc(numStops * sizeof(XFixed));
645
646
if (colors == NULL || stops == NULL) {
647
if (colors != NULL) {
648
free(colors);
649
}
650
if (stops != NULL) {
651
free(stops);
652
}
653
(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
654
(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
655
return -1;
656
}
657
658
for (i=0; i < numStops; i++) {
659
stops[i] = XDoubleToFixed(fractions[i]);
660
colors[i].alpha = pixels[i*4 + 0];
661
colors[i].red = pixels[i*4 + 1];
662
colors[i].green = pixels[i*4 + 2];
663
colors[i].blue = pixels[i*4 + 3];
664
}
665
#ifdef __solaris__
666
if (XRenderCreateRadialGradientFunc != NULL) {
667
gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);
668
}
669
#else
670
gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);
671
#endif
672
free(colors);
673
free(stops);
674
675
(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
676
(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
677
678
679
if (gradient != 0) {
680
pict_attr.repeat = repeat;
681
XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
682
}
683
684
return (jint) gradient;
685
}
686
687
JNIEXPORT void JNICALL
688
Java_sun_java2d_xr_XRBackendNative_setFilter
689
(JNIEnv *env, jobject this, jint picture, jint filter) {
690
691
char * filterName = "fast";
692
693
switch(filter) {
694
case 0:
695
filterName = "fast";
696
break;
697
698
case 1:
699
filterName = "good";
700
break;
701
702
case 2:
703
filterName = "best";
704
break;
705
}
706
707
XRenderSetPictureFilter(awt_display, (Picture) picture, filterName, NULL, 0);
708
}
709
710
JNIEXPORT void JNICALL
711
Java_sun_java2d_xr_XRBackendNative_XRSetClipNative
712
(JNIEnv *env, jclass xsd, jlong dst,
713
jint x1, jint y1, jint x2, jint y2,
714
jobject complexclip, jboolean isGC)
715
{
716
int numrects;
717
XRectangle rects[256];
718
XRectangle *pRect = rects;
719
720
numrects = RegionToYXBandedRectangles(env,
721
x1, y1, x2, y2, complexclip,
722
&pRect, 256);
723
724
if (isGC == JNI_TRUE) {
725
if (dst != (jlong) 0) {
726
XSetClipRectangles(awt_display, (GC) jlong_to_ptr(dst), 0, 0, pRect, numrects, YXBanded);
727
}
728
} else {
729
XRenderSetPictureClipRectangles (awt_display, (Picture) dst, 0, 0, pRect, numrects);
730
}
731
732
if (pRect != rects) {
733
free(pRect);
734
}
735
}
736
737
JNIEXPORT void JNICALL
738
Java_sun_java2d_xr_XRBackendNative_putMaskNative
739
(JNIEnv *env, jclass cls, jint drawable, jlong gc, jbyteArray imageData,
740
jint sx, jint sy, jint dx, jint dy, jint width, jint height,
741
jint maskOff, jint maskScan, jfloat ea, jlong imgPtr) {
742
743
int line, pix;
744
char *mask;
745
char *defaultData;
746
XImage *defaultImg, *img;
747
jboolean imageFits;
748
749
if ((mask = (char *)
750
(*env)->GetPrimitiveArrayCritical(env, imageData, NULL)) == NULL) {
751
return;
752
}
753
754
defaultImg = (XImage *) jlong_to_ptr(imgPtr);
755
756
if (ea != 1.0f) {
757
for (line=0; line < height; line++) {
758
for (pix=0; pix < width; pix++) {
759
size_t index = (size_t) maskScan * line + pix + maskOff;
760
mask[index] = (((unsigned char) mask[index])*ea);
761
}
762
}
763
}
764
765
/*
766
* 1. If existing XImage and supplied buffer match, only adjust the data pointer
767
* 2. If existing XImage is large enough to hold the data but does not match in
768
* scan the data is copied to fit the XImage.
769
* 3. If data is larger than the existing XImage a new temporary XImage is
770
* allocated.
771
* The default XImage is optimized for the AA tiles, which are currently 32x32.
772
*/
773
defaultData = defaultImg->data;
774
img = defaultImg;
775
imageFits = defaultImg->width >= width && defaultImg->height >= height;
776
777
if (imageFits &&
778
maskOff == defaultImg->xoffset && maskScan == defaultImg->bytes_per_line) {
779
defaultImg->data = mask;
780
} else {
781
if (imageFits) {
782
for (line=0; line < height; line++) {
783
for (pix=0; pix < width; pix++) {
784
img->data[(size_t) line * img->bytes_per_line + pix] =
785
(unsigned char) (mask[(size_t) maskScan * line + pix + maskOff]);
786
}
787
}
788
} else {
789
img = XCreateImage(awt_display, NULL, 8, ZPixmap,
790
maskOff, mask, maskScan, height, 8, 0);
791
}
792
}
793
794
XPutImage(awt_display, (Pixmap) drawable, (GC) jlong_to_ptr(gc),
795
img, 0, 0, 0, 0, width, height);
796
(*env)->ReleasePrimitiveArrayCritical(env, imageData, mask, JNI_ABORT);
797
798
if (img != defaultImg) {
799
img->data = NULL;
800
XDestroyImage(img);
801
}
802
defaultImg->data = defaultData;
803
}
804
805
JNIEXPORT void JNICALL
806
Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative
807
(JNIEnv *env, jclass cls, jint glyphSet,
808
jlongArray glyphInfoPtrsArray, jint glyphCnt,
809
jbyteArray pixelDataArray, int pixelDataLength) {
810
jlong *glyphInfoPtrs;
811
unsigned char *pixelData;
812
int i;
813
814
if (MAX_PAYLOAD / (sizeof(XGlyphInfo) + sizeof(Glyph))
815
< (unsigned)glyphCnt) {
816
/* glyphCnt too big, payload overflow */
817
return;
818
}
819
820
XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt);
821
Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);
822
823
if (xginfo == NULL || gid == NULL) {
824
if (xginfo != NULL) {
825
free(xginfo);
826
}
827
if (gid != NULL) {
828
free(gid);
829
}
830
return;
831
}
832
833
if ((glyphInfoPtrs = (jlong *)(*env)->
834
GetPrimitiveArrayCritical(env, glyphInfoPtrsArray, NULL)) == NULL)
835
{
836
free(xginfo);
837
free(gid);
838
return;
839
}
840
841
if ((pixelData = (unsigned char *)
842
(*env)->GetPrimitiveArrayCritical(env, pixelDataArray, NULL)) == NULL)
843
{
844
(*env)->ReleasePrimitiveArrayCritical(env,
845
glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
846
free(xginfo);
847
free(gid);
848
return;
849
}
850
851
for (i=0; i < glyphCnt; i++) {
852
GlyphInfo *jginfo = (GlyphInfo *) jlong_to_ptr(glyphInfoPtrs[i]);
853
854
// 'jginfo->cellInfo' is of type 'void*'
855
// (see definition of 'GlyphInfo' in fontscalerdefs.h)
856
// 'Glyph' is typedefed to 'unsigned long'
857
// (see http://www.x.org/releases/X11R7.7/doc/libXrender/libXrender.txt)
858
// Maybe we should assert that (sizeof(void*) == sizeof(Glyph)) ?
859
gid[i] = (Glyph) (jginfo->cellInfo);
860
xginfo[i].x = (-jginfo->topLeftX);
861
xginfo[i].y = (-jginfo->topLeftY);
862
xginfo[i].width = jginfo->width;
863
xginfo[i].height = jginfo->height;
864
xginfo[i].xOff = round(jginfo->advanceX);
865
xginfo[i].yOff = round(jginfo->advanceY);
866
}
867
868
XRenderAddGlyphs(awt_display, glyphSet, &gid[0], &xginfo[0], glyphCnt,
869
(const char*)pixelData, pixelDataLength);
870
871
(*env)->ReleasePrimitiveArrayCritical(env, glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
872
(*env)->ReleasePrimitiveArrayCritical(env, pixelDataArray, pixelData, JNI_ABORT);
873
874
free(xginfo);
875
free(gid);
876
}
877
878
JNIEXPORT void JNICALL
879
Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative
880
(JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) {
881
882
if (MAX_PAYLOAD / sizeof(Glyph) < (unsigned)glyphCnt) {
883
/* glyphCnt too big, payload overflow */
884
return;
885
}
886
887
/* The glyph ids are 32 bit but may be stored in a 64 bit long on
888
* a 64 bit architecture. So optimise the 32 bit case to avoid
889
* extra stack or heap allocations by directly referencing the
890
* underlying Java array and only allocate on 64 bit.
891
*/
892
if (sizeof(jint) == sizeof(Glyph)) {
893
jint *gids =
894
(*env)->GetPrimitiveArrayCritical(env, gidArray, NULL);
895
if (gids == NULL) {
896
return;
897
} else {
898
XRenderFreeGlyphs(awt_display,
899
(GlyphSet)glyphSet, (Glyph *)gids, glyphCnt);
900
(*env)->ReleasePrimitiveArrayCritical(env, gidArray,
901
gids, JNI_ABORT);
902
}
903
return;
904
} else {
905
Glyph stack_ids[64];
906
Glyph *gids = NULL;
907
jint* jgids = NULL;
908
int i;
909
910
if (glyphCnt <= 64) {
911
gids = stack_ids;
912
} else {
913
gids = (Glyph *)malloc(sizeof(Glyph) * glyphCnt);
914
if (gids == NULL) {
915
return;
916
}
917
}
918
jgids = (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL);
919
if (jgids == NULL) {
920
if (gids != stack_ids) {
921
free(gids);
922
}
923
return;
924
}
925
for (i=0; i < glyphCnt; i++) {
926
gids[i] = jgids[i];
927
}
928
XRenderFreeGlyphs(awt_display,
929
(GlyphSet) glyphSet, gids, glyphCnt);
930
(*env)->ReleasePrimitiveArrayCritical(env, gidArray,
931
jgids, JNI_ABORT);
932
if (gids != stack_ids) {
933
free(gids);
934
}
935
}
936
}
937
938
JNIEXPORT jint JNICALL
939
Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative
940
(JNIEnv *env, jclass cls, jlong format) {
941
return XRenderCreateGlyphSet(awt_display, (XRenderPictFormat *) jlong_to_ptr(format));
942
}
943
944
JNIEXPORT void JNICALL
945
Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative
946
(JNIEnv *env, jclass cls, jint op, jint src, jint dst,
947
jint sx, jint sy, jlong maskFmt, jintArray eltArray,
948
jintArray glyphIDArray, jint eltCnt, jint glyphCnt) {
949
jint i;
950
jint *ids;
951
jint *elts;
952
XGlyphElt32 *xelts;
953
unsigned int *xids;
954
XGlyphElt32 selts[24];
955
unsigned int sids[256];
956
int charCnt = 0;
957
958
if ((MAX_PAYLOAD / sizeof(XGlyphElt32) < (unsigned)eltCnt)
959
|| (MAX_PAYLOAD / sizeof(unsigned int) < (unsigned)glyphCnt)
960
|| ((MAX_PAYLOAD - sizeof(XGlyphElt32)*(unsigned)eltCnt) /
961
sizeof(unsigned int) < (unsigned)glyphCnt))
962
{
963
/* (eltCnt, glyphCnt) too big, payload overflow */
964
return;
965
}
966
967
if (eltCnt <= 24) {
968
xelts = &selts[0];
969
}else {
970
xelts = (XGlyphElt32 *) malloc(sizeof(XGlyphElt32) * eltCnt);
971
if (xelts == NULL) {
972
return;
973
}
974
}
975
976
if (glyphCnt <= 256) {
977
xids = &sids[0];
978
} else {
979
xids = (unsigned int*)malloc(sizeof(unsigned int) * glyphCnt);
980
if (xids == NULL) {
981
if (xelts != &selts[0]) {
982
free(xelts);
983
}
984
return;
985
}
986
}
987
988
if ((ids = (jint *)
989
(*env)->GetPrimitiveArrayCritical(env, glyphIDArray, NULL)) == NULL) {
990
if (xelts != &selts[0]) {
991
free(xelts);
992
}
993
if (xids != &sids[0]) {
994
free(xids);
995
}
996
return;
997
}
998
if ((elts = (jint *)
999
(*env)->GetPrimitiveArrayCritical(env, eltArray, NULL)) == NULL) {
1000
(*env)->ReleasePrimitiveArrayCritical(env,
1001
glyphIDArray, ids, JNI_ABORT);
1002
if (xelts != &selts[0]) {
1003
free(xelts);
1004
}
1005
if (xids != &sids[0]) {
1006
free(xids);
1007
}
1008
return;
1009
}
1010
1011
for (i=0; i < glyphCnt; i++) {
1012
xids[i] = ids[i];
1013
}
1014
1015
for (i=0; i < eltCnt; i++) {
1016
xelts[i].nchars = elts[i*4 + 0];
1017
xelts[i].xOff = elts[i*4 + 1];
1018
xelts[i].yOff = elts[i*4 + 2];
1019
xelts[i].glyphset = (GlyphSet) elts[i*4 + 3];
1020
xelts[i].chars = &xids[charCnt];
1021
1022
charCnt += xelts[i].nchars;
1023
}
1024
1025
XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst,
1026
(XRenderPictFormat *) jlong_to_ptr(maskFmt),
1027
sx, sy, 0, 0, xelts, eltCnt);
1028
1029
(*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT);
1030
(*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT);
1031
1032
if (xelts != &selts[0]) {
1033
free(xelts);
1034
}
1035
1036
if (xids != &sids[0]) {
1037
free(xids);
1038
}
1039
}
1040
1041
JNIEXPORT void JNICALL
1042
Java_sun_java2d_xr_XRBackendNative_setGCMode
1043
(JNIEnv *env, jobject this, jlong gc, jboolean copy) {
1044
GC xgc = (GC) jlong_to_ptr(gc);
1045
1046
if (copy == JNI_TRUE) {
1047
XSetFunction(awt_display, xgc, GXcopy);
1048
} else {
1049
XSetFunction(awt_display, xgc, GXxor);
1050
}
1051
}
1052
1053
JNIEXPORT void JNICALL
1054
Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative
1055
(JNIEnv *env, jclass xsd, jint dst, jlong gc,
1056
jintArray rectArray, jint rectCnt) {
1057
int i;
1058
jint* rects;
1059
XRectangle *xRects;
1060
XRectangle sRects[256];
1061
1062
if (rectCnt <= 256) {
1063
xRects = &sRects[0];
1064
} else {
1065
if (MAXUINT / sizeof(XRectangle) < (unsigned)rectCnt) {
1066
/* rectCnt too big, integer overflow */
1067
return;
1068
}
1069
1070
xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
1071
if (xRects == NULL) {
1072
return;
1073
}
1074
}
1075
1076
if ((rects = (jint*)
1077
(*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
1078
if (xRects != &sRects[0]) {
1079
free(xRects);
1080
}
1081
return;
1082
}
1083
1084
for (i=0; i < rectCnt; i++) {
1085
xRects[i].x = rects[i*4 + 0];
1086
xRects[i].y = rects[i*4 + 1];
1087
xRects[i].width = rects[i*4 + 2];
1088
xRects[i].height = rects[i*4 + 3];
1089
}
1090
1091
XFillRectangles(awt_display, (Drawable) dst, (GC) jlong_to_ptr(gc), xRects, rectCnt);
1092
1093
(*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
1094
if (xRects != &sRects[0]) {
1095
free(xRects);
1096
}
1097
}
1098
1099
JNIEXPORT void JNICALL
1100
Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative
1101
(JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt,
1102
jint dst, jint srcX, jint srcY, jintArray trapArray) {
1103
jint *traps;
1104
1105
if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) {
1106
return;
1107
}
1108
1109
XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst,
1110
(XRenderPictFormat *) jlong_to_ptr(maskFmt),
1111
srcX, srcY, (XTrapezoid *) (traps+5), traps[0]);
1112
1113
(*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT);
1114
}
1115
1116