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