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/X11Renderer.c
32288 views
1
/*
2
* Copyright (c) 2000, 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 "sun_java2d_x11_X11Renderer.h"
27
28
#include "X11SurfaceData.h"
29
#include "SpanIterator.h"
30
#include "Trace.h"
31
#include "ProcessPath.h"
32
#include "GraphicsPrimitiveMgr.h"
33
34
35
#include <jlong.h>
36
37
#ifndef HEADLESS
38
#define POLYTEMPSIZE (int)(256 / sizeof(XPoint))
39
#define ABS(n) (((n) < 0) ? -(n) : (n))
40
41
#define MAX_SHORT 32767
42
#define MIN_SHORT (-32768)
43
44
#define CLAMP_TO_SHORT(x) (((x) > MAX_SHORT) \
45
? MAX_SHORT \
46
: ((x) < MIN_SHORT) \
47
? MIN_SHORT \
48
: (x))
49
50
#define CLAMP_TO_USHORT(x) (((x) > 65535) ? 65535 : ((x) < 0) ? 0 : (x))
51
52
#define DF_MAX_XPNTS 256
53
54
typedef struct {
55
Drawable drawable;
56
GC gc;
57
XPoint *pPoints;
58
XPoint dfPoints[DF_MAX_XPNTS];
59
jint npoints;
60
jint maxpoints;
61
} XDrawHandlerData;
62
63
#define XDHD_INIT(PTR, _GC, DRAWABLE) \
64
do { \
65
(PTR)->pPoints = (PTR)->dfPoints; \
66
(PTR)->npoints = 0; \
67
(PTR)->maxpoints = DF_MAX_XPNTS; \
68
(PTR)->gc = (_GC); \
69
(PTR)->drawable = (DRAWABLE); \
70
} while(0)
71
72
#define XDHD_RESET(PTR) \
73
do { \
74
(PTR)->npoints = 0; \
75
} while(0)
76
77
78
#define XDHD_ADD_POINT(PTR, X, Y) \
79
do { \
80
XPoint* _pnts = (PTR)->pPoints; \
81
jint _npnts = (PTR)->npoints; \
82
if (_npnts >= (PTR)->maxpoints) { \
83
jint newMax = (PTR)->maxpoints*2; \
84
if ((PTR)->pPoints == (PTR)->dfPoints) { \
85
(PTR)->pPoints = (XPoint*)malloc(newMax*sizeof(XPoint)); \
86
memcpy((PTR)->pPoints, _pnts, _npnts*sizeof(XPoint)); \
87
} else { \
88
(PTR)->pPoints = (XPoint*)realloc( \
89
_pnts, newMax*sizeof(XPoint)); \
90
} \
91
_pnts = (PTR)->pPoints; \
92
(PTR)->maxpoints = newMax; \
93
} \
94
_pnts += _npnts; \
95
_pnts->x = X; \
96
_pnts->y = Y; \
97
(PTR)->npoints = _npnts + 1; \
98
} while(0)
99
100
#define XDHD_FREE_POINTS(PTR) \
101
do { \
102
if ((PTR)->pPoints != (PTR)->dfPoints) { \
103
free((PTR)->pPoints); \
104
} \
105
} while(0)
106
107
108
static void
109
awt_drawArc(JNIEnv * env, jint drawable, GC xgc,
110
int x, int y, int w, int h,
111
int startAngle, int endAngle,
112
int filled)
113
{
114
int s, e;
115
116
if (w < 0 || h < 0) {
117
return;
118
}
119
if (endAngle >= 360 || endAngle <= -360) {
120
s = 0;
121
e = 360 * 64;
122
} else {
123
s = (startAngle % 360) * 64;
124
e = endAngle * 64;
125
}
126
if (filled == 0) {
127
XDrawArc(awt_display, drawable, xgc, x, y, w, h, s, e);
128
} else {
129
XFillArc(awt_display, drawable, xgc, x, y, w, h, s, e);
130
}
131
}
132
133
/*
134
* Copy vertices from xcoordsArray and ycoordsArray to a buffer
135
* of XPoint structures, translating by transx and transy and
136
* collapsing empty segments out of the list as we go.
137
* The number of points to be converted should be guaranteed
138
* to be more than 2 by the caller and is stored at *pNpoints.
139
* The resulting number of uncollapsed unique translated vertices
140
* will be stored back into the location *pNpoints.
141
* The points pointer is guaranteed to be pointing to an area of
142
* memory large enough for POLYTEMPSIZE points and a larger
143
* area of memory is allocated (and returned) if that is not enough.
144
*/
145
static XPoint *
146
transformPoints(JNIEnv * env,
147
jintArray xcoordsArray, jintArray ycoordsArray,
148
jint transx, jint transy,
149
XPoint * points, int *pNpoints, int close)
150
{
151
int npoints = *pNpoints;
152
jint *xcoords, *ycoords;
153
154
xcoords = (jint *)
155
(*env)->GetPrimitiveArrayCritical(env, xcoordsArray, NULL);
156
if (xcoords == NULL) {
157
return 0;
158
}
159
160
ycoords = (jint *)
161
(*env)->GetPrimitiveArrayCritical(env, ycoordsArray, NULL);
162
if (ycoords == NULL) {
163
(*env)->ReleasePrimitiveArrayCritical(env, xcoordsArray, xcoords,
164
JNI_ABORT);
165
return 0;
166
}
167
168
if (close) {
169
close = (xcoords[npoints - 1] != xcoords[0] ||
170
ycoords[npoints - 1] != ycoords[0]);
171
if (close) {
172
npoints++;
173
}
174
}
175
if (npoints > POLYTEMPSIZE) {
176
points = (XPoint *) malloc(sizeof(XPoint) * npoints);
177
}
178
if (points != NULL) {
179
int in, out;
180
int oldx = CLAMP_TO_SHORT(xcoords[0] + transx);
181
int oldy = CLAMP_TO_SHORT(ycoords[0] + transy);
182
points[0].x = oldx;
183
points[0].y = oldy;
184
if (close) {
185
npoints--;
186
}
187
for (in = 1, out = 1; in < npoints; in++) {
188
int newx = CLAMP_TO_SHORT(xcoords[in] + transx);
189
int newy = CLAMP_TO_SHORT(ycoords[in] + transy);
190
if (newx != oldx || newy != oldy) {
191
points[out].x = newx;
192
points[out].y = newy;
193
out++;
194
oldx = newx;
195
oldy = newy;
196
}
197
}
198
if (out == 1) {
199
points[1].x = oldx;
200
points[1].y = oldy;
201
out = 2;
202
} else if (close) {
203
points[out++] = points[0];
204
}
205
*pNpoints = out;
206
}
207
208
(*env)->ReleasePrimitiveArrayCritical(env, xcoordsArray, xcoords,
209
JNI_ABORT);
210
(*env)->ReleasePrimitiveArrayCritical(env, ycoordsArray, ycoords,
211
JNI_ABORT);
212
213
return points;
214
}
215
#endif /* !HEADLESS */
216
217
/*
218
* Class: sun_java2d_x11_X11Renderer
219
* Method: XDrawLine
220
* Signature: (IJIIII)V
221
*/
222
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawLine
223
(JNIEnv *env, jobject xr,
224
jlong pXSData, jlong xgc,
225
jint x1, jint y1, jint x2, jint y2)
226
{
227
#ifndef HEADLESS
228
X11SDOps *xsdo = (X11SDOps *) pXSData;
229
230
if (xsdo == NULL) {
231
return;
232
}
233
234
XDrawLine(awt_display, xsdo->drawable, (GC) xgc,
235
CLAMP_TO_SHORT(x1), CLAMP_TO_SHORT(y1),
236
CLAMP_TO_SHORT(x2), CLAMP_TO_SHORT(y2));
237
X11SD_DirectRenderNotify(env, xsdo);
238
#endif /* !HEADLESS */
239
}
240
241
/*
242
* Class: sun_java2d_x11_X11Renderer
243
* Method: XDrawRect
244
* Signature: (IJIIII)V
245
*/
246
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawRect
247
(JNIEnv *env, jobject xr,
248
jlong pXSData, jlong xgc,
249
jint x, jint y, jint w, jint h)
250
{
251
#ifndef HEADLESS
252
X11SDOps *xsdo = (X11SDOps *) pXSData;
253
254
if (xsdo == NULL || w < 0 || h < 0) {
255
return;
256
}
257
258
if (w < 2 || h < 2) {
259
/* REMIND: This optimization assumes thin lines. */
260
/*
261
* This optimization not only simplifies the processing
262
* of a particular degenerate case, but it protects against
263
* the anomalies of various X11 implementations that draw
264
* nothing for degenerate Polygons and Rectangles.
265
*/
266
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,
267
CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),
268
CLAMP_TO_USHORT(w+1), CLAMP_TO_USHORT(h+1));
269
} else {
270
XDrawRectangle(awt_display, xsdo->drawable, (GC) xgc,
271
CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),
272
CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h));
273
}
274
X11SD_DirectRenderNotify(env, xsdo);
275
#endif /* !HEADLESS */
276
}
277
278
/*
279
* Class: sun_java2d_x11_X11Renderer
280
* Method: XDrawRoundRect
281
* Signature: (IJIIIIII)V
282
*/
283
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawRoundRect
284
(JNIEnv *env, jobject xr,
285
jlong pXSData, jlong xgc,
286
jint x, jint y, jint w, jint h,
287
jint arcW, jint arcH)
288
{
289
#ifndef HEADLESS
290
long ty1, ty2, tx1, tx2, cx, cy, cxw, cyh,
291
halfW, halfH, leftW, rightW, topH, bottomH;
292
X11SDOps *xsdo = (X11SDOps *) pXSData;
293
294
if (xsdo == NULL || w < 0 || h < 0) {
295
return;
296
}
297
298
arcW = ABS(arcW);
299
arcH = ABS(arcH);
300
if (arcW > w) {
301
arcW = w;
302
}
303
if (arcH > h) {
304
arcH = h;
305
}
306
307
if (arcW == 0 || arcH == 0) {
308
Java_sun_java2d_x11_X11Renderer_XDrawRect(env, xr, pXSData, xgc,
309
x, y, w, h);
310
return;
311
}
312
313
halfW = (arcW / 2);
314
halfH = (arcH / 2);
315
316
/* clamp to short bounding box of round rectangle */
317
cx = CLAMP_TO_SHORT(x);
318
cy = CLAMP_TO_SHORT(y);
319
cxw = CLAMP_TO_SHORT(x + w);
320
cyh = CLAMP_TO_SHORT(y + h);
321
322
/* clamp to short coordinates of lines */
323
tx1 = CLAMP_TO_SHORT(x + halfW + 1);
324
tx2 = CLAMP_TO_SHORT(x + w - halfW - 1);
325
ty1 = CLAMP_TO_SHORT(y + halfH + 1);
326
ty2 = CLAMP_TO_SHORT(y + h - halfH - 1);
327
328
/*
329
* recalculate heightes and widthes of round parts
330
* to minimize distortions in visible area
331
*/
332
leftW = (tx1 - cx) * 2;
333
rightW = (cxw - tx2) * 2;
334
topH = (ty1 - cy) * 2;
335
bottomH = (cyh - ty2) * 2;
336
337
awt_drawArc(env, xsdo->drawable, (GC) xgc,
338
cx, cy, leftW, topH,
339
90, 90, JNI_FALSE);
340
awt_drawArc(env, xsdo->drawable, (GC) xgc,
341
cxw - rightW, cy, rightW, topH,
342
0, 90, JNI_FALSE);
343
awt_drawArc(env, xsdo->drawable, (GC) xgc,
344
cx, cyh - bottomH, leftW, bottomH,
345
180, 90, JNI_FALSE);
346
awt_drawArc(env, xsdo->drawable, (GC) xgc,
347
cxw - rightW, cyh - bottomH, rightW, bottomH,
348
270, 90, JNI_FALSE);
349
350
if (tx1 <= tx2) {
351
XDrawLine(awt_display, xsdo->drawable, (GC) xgc,
352
tx1, cy, tx2, cy);
353
if (h > 0) {
354
XDrawLine(awt_display, xsdo->drawable, (GC) xgc,
355
tx1, cyh, tx2, cyh);
356
}
357
}
358
if (ty1 <= ty2) {
359
XDrawLine(awt_display, xsdo->drawable, (GC) xgc,
360
cx, ty1, cx, ty2);
361
if (w > 0) {
362
XDrawLine(awt_display, xsdo->drawable, (GC) xgc,
363
cxw, ty1, cxw, ty2);
364
}
365
}
366
X11SD_DirectRenderNotify(env, xsdo);
367
#endif /* !HEADLESS */
368
}
369
370
/*
371
* Class: sun_java2d_x11_X11Renderer
372
* Method: XDrawOval
373
* Signature: (IJIIII)V
374
*/
375
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawOval
376
(JNIEnv *env, jobject xr,
377
jlong pXSData, jlong xgc,
378
jint x, jint y, jint w, jint h)
379
{
380
#ifndef HEADLESS
381
X11SDOps *xsdo = (X11SDOps *) pXSData;
382
383
if (xsdo == NULL) {
384
return;
385
}
386
387
if (w < 2 || h < 2) {
388
/*
389
* Fix for 4205762 - 1x1 ovals do not draw on Ultra1, Creator3d
390
* (related to 4411814 on Windows platform)
391
* Really small ovals degenerate to simple rectangles as they
392
* have no curvature or enclosed area. Use XFillRectangle
393
* for speed and to deal better with degenerate sizes.
394
*/
395
if (w >= 0 && h >= 0) {
396
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,
397
x, y, w+1, h+1);
398
}
399
} else {
400
awt_drawArc(env, xsdo->drawable, (GC) xgc,
401
x, y, w, h, 0, 360, JNI_FALSE);
402
}
403
X11SD_DirectRenderNotify(env, xsdo);
404
#endif /* !HEADLESS */
405
}
406
407
/*
408
* Class: sun_java2d_x11_X11Renderer
409
* Method: XDrawArc
410
* Signature: (IJIIIIII)V
411
*/
412
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawArc
413
(JNIEnv *env, jobject xr,
414
jlong pXSData, jlong xgc,
415
jint x, jint y, jint w, jint h,
416
jint angleStart, jint angleExtent)
417
{
418
#ifndef HEADLESS
419
X11SDOps *xsdo = (X11SDOps *) pXSData;
420
421
if (xsdo == NULL) {
422
return;
423
}
424
425
awt_drawArc(env, xsdo->drawable, (GC) xgc,
426
x, y, w, h, angleStart, angleExtent, JNI_FALSE);
427
X11SD_DirectRenderNotify(env, xsdo);
428
#endif /* !HEADLESS */
429
}
430
431
/*
432
* Class: sun_java2d_x11_X11Renderer
433
* Method: XDrawPoly
434
* Signature: (IJII[I[IIZ)V
435
*/
436
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawPoly
437
(JNIEnv *env, jobject xr,
438
jlong pXSData, jlong xgc,
439
jint transx, jint transy,
440
jintArray xcoordsArray, jintArray ycoordsArray, jint npoints,
441
jboolean isclosed)
442
{
443
#ifndef HEADLESS
444
XPoint pTmp[POLYTEMPSIZE], *points;
445
X11SDOps *xsdo = (X11SDOps *) pXSData;
446
447
if (xsdo == NULL) {
448
return;
449
}
450
451
if (JNU_IsNull(env, xcoordsArray) || JNU_IsNull(env, ycoordsArray)) {
452
JNU_ThrowNullPointerException(env, "coordinate array");
453
return;
454
}
455
if ((*env)->GetArrayLength(env, ycoordsArray) < npoints ||
456
(*env)->GetArrayLength(env, xcoordsArray) < npoints)
457
{
458
JNU_ThrowArrayIndexOutOfBoundsException(env, "coordinate array");
459
return;
460
}
461
462
if (npoints < 2) {
463
return;
464
}
465
466
points = transformPoints(env, xcoordsArray, ycoordsArray, transx, transy,
467
pTmp, (int *)&npoints, isclosed);
468
if (points != 0) {
469
if (npoints == 2) {
470
/*
471
* Some X11 implementations fail to draw anything for
472
* simple 2 point polygons where the vertices are the
473
* same point even though this violates the X11
474
* specification. For simplicity we will dispatch all
475
* 2 point polygons through XDrawLine even if they are
476
* non-degenerate as this may invoke less processing
477
* down the line than a Poly primitive anyway.
478
*/
479
XDrawLine(awt_display, xsdo->drawable, (GC) xgc,
480
points[0].x, points[0].y,
481
points[1].x, points[1].y);
482
} else {
483
XDrawLines(awt_display, xsdo->drawable, (GC) xgc,
484
points, npoints, CoordModeOrigin);
485
}
486
if (points != pTmp) {
487
free(points);
488
}
489
X11SD_DirectRenderNotify(env, xsdo);
490
}
491
#endif /* !HEADLESS */
492
}
493
494
static void storeLine(DrawHandler* hnd,
495
jint x0, jint y0, jint x1, jint y1)
496
{
497
#ifndef HEADLESS
498
XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData);
499
500
XDHD_ADD_POINT(dhnd, x0, y0);
501
XDHD_ADD_POINT(dhnd, x1, y1);
502
#endif /* !HEADLESS */
503
}
504
505
static void storePoint(DrawHandler* hnd, jint x0, jint y0) {
506
#ifndef HEADLESS
507
XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData);
508
509
XDHD_ADD_POINT(dhnd, x0, y0);
510
#endif /* !HEADLESS */
511
}
512
513
static void drawSubPath(ProcessHandler* hnd) {
514
#ifndef HEADLESS
515
XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->dhnd->pData);
516
XPoint *points = dhnd->pPoints;
517
518
switch (dhnd->npoints) {
519
case 0:
520
/* No-op */
521
break;
522
case 1:
523
/* Draw the single pixel */
524
XFillRectangle(awt_display, dhnd->drawable, dhnd->gc,
525
points[0].x, points[0].y, 1, 1);
526
break;
527
case 2:
528
/*
529
* The XDrawLines method for some X11 implementations
530
* fails to draw anything for simple 2 point polygons
531
* where the vertices are the same point even though
532
* this violates the X11 specification. For simplicity
533
* we will dispatch all 2 point polygons through XDrawLine
534
* even if they are non-degenerate as this may invoke
535
* less processing down the line than a poly primitive anyway.
536
*/
537
XDrawLine(awt_display, dhnd->drawable, dhnd->gc,
538
points[0].x, points[0].y,
539
points[1].x, points[1].y);
540
break;
541
default:
542
/* Draw the entire polyline */
543
XDrawLines(awt_display, dhnd->drawable, dhnd->gc, points,
544
dhnd->npoints, CoordModeOrigin);
545
break;
546
}
547
548
XDHD_RESET(dhnd);
549
#endif /* !HEADLESS */
550
}
551
552
static void drawScanline(DrawHandler* hnd, jint x0, jint x1, jint y0)
553
{
554
#ifndef HEADLESS
555
XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData);
556
557
XDrawLine(awt_display, dhnd->drawable, dhnd->gc, x0, y0, x1, y0);
558
#endif /* !HEADLESS */
559
}
560
561
/*
562
* Class: sun_java2d_x11_X11Renderer
563
* Method: XDoPath
564
* Signature: (Lsun/java2d/SunGraphics2D;JJIILjava/awt/geom/Path2D/Float;Z)V
565
*/
566
JNIEXPORT void JNICALL
567
Java_sun_java2d_x11_X11Renderer_XDoPath
568
(JNIEnv *env, jobject self, jobject sg2d, jlong pXSData, jlong xgc,
569
jint transX, jint transY, jobject p2df, jboolean isFill)
570
{
571
#ifndef HEADLESS
572
X11SDOps *xsdo = (X11SDOps *) pXSData;
573
jarray typesArray;
574
jobject pointArray;
575
jarray coordsArray;
576
jint numTypes;
577
jint fillRule;
578
jint maxCoords;
579
jbyte *types;
580
jfloat *coords;
581
XDrawHandlerData dHData;
582
DrawHandler drawHandler = {
583
NULL, NULL, NULL,
584
MIN_SHORT, MIN_SHORT, MAX_SHORT, MAX_SHORT,
585
0, 0, 0, 0,
586
NULL
587
};
588
PHStroke stroke;
589
jboolean ok = JNI_TRUE;
590
591
if (xsdo == NULL) {
592
return;
593
}
594
595
if (isFill) {
596
fillRule = (*env)->GetIntField(env, p2df, path2DWindingRuleID);
597
}
598
599
typesArray = (jarray)(*env)->GetObjectField(env, p2df, path2DTypesID);
600
coordsArray = (jarray)(*env)->GetObjectField(env, p2df,
601
path2DFloatCoordsID);
602
if (coordsArray == NULL) {
603
JNU_ThrowNullPointerException(env, "coordinates array");
604
return;
605
}
606
numTypes = (*env)->GetIntField(env, p2df, path2DNumTypesID);
607
if ((*env)->GetArrayLength(env, typesArray) < numTypes) {
608
JNU_ThrowArrayIndexOutOfBoundsException(env, "types array");
609
return;
610
}
611
612
XDHD_INIT(&dHData, (GC)xgc, xsdo->drawable);
613
drawHandler.pData = &dHData;
614
615
stroke = (((*env)->GetIntField(env, sg2d, sg2dStrokeHintID) ==
616
sunHints_INTVAL_STROKE_PURE)
617
? PH_STROKE_PURE
618
: PH_STROKE_DEFAULT);
619
620
maxCoords = (*env)->GetArrayLength(env, coordsArray);
621
coords = (jfloat*)
622
(*env)->GetPrimitiveArrayCritical(env, coordsArray, NULL);
623
if (coords != NULL) {
624
types = (jbyte*)
625
(*env)->GetPrimitiveArrayCritical(env, typesArray, NULL);
626
if (types != NULL) {
627
if (isFill) {
628
drawHandler.pDrawScanline = &drawScanline;
629
ok = doFillPath(&drawHandler,
630
transX, transY,
631
coords, maxCoords,
632
types, numTypes,
633
stroke, fillRule);
634
} else {
635
drawHandler.pDrawLine = &storeLine;
636
drawHandler.pDrawPixel = &storePoint;
637
ok = doDrawPath(&drawHandler, &drawSubPath,
638
transX, transY,
639
coords, maxCoords,
640
types, numTypes,
641
stroke);
642
}
643
(*env)->ReleasePrimitiveArrayCritical(env, typesArray, types,
644
JNI_ABORT);
645
}
646
(*env)->ReleasePrimitiveArrayCritical(env, coordsArray, coords,
647
JNI_ABORT);
648
if (!ok) {
649
JNU_ThrowArrayIndexOutOfBoundsException(env, "coords array");
650
}
651
}
652
653
XDHD_FREE_POINTS(&dHData);
654
X11SD_DirectRenderNotify(env, xsdo);
655
#endif /* !HEADLESS */
656
}
657
658
/*
659
* Class: sun_java2d_x11_X11Renderer
660
* Method: XFillRect
661
* Signature: (IJIIII)V
662
*/
663
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillRect
664
(JNIEnv *env, jobject xr,
665
jlong pXSData, jlong xgc,
666
jint x, jint y, jint w, jint h)
667
{
668
#ifndef HEADLESS
669
X11SDOps *xsdo = (X11SDOps *) pXSData;
670
671
if (xsdo == NULL) {
672
return;
673
}
674
675
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,
676
CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),
677
CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h));
678
X11SD_DirectRenderNotify(env, xsdo);
679
#endif /* !HEADLESS */
680
}
681
682
/*
683
* Class: sun_java2d_x11_X11Renderer
684
* Method: XFillRoundRect
685
* Signature: (IJIIIIII)V
686
*/
687
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillRoundRect
688
(JNIEnv *env, jobject xr,
689
jlong pXSData, jlong xgc,
690
jint x, jint y, jint w, jint h,
691
jint arcW, jint arcH)
692
{
693
#ifndef HEADLESS
694
long ty1, ty2, tx1, tx2, cx, cy, cxw, cyh,
695
halfW, halfH, leftW, rightW, topH, bottomH;
696
X11SDOps *xsdo = (X11SDOps *) pXSData;
697
698
if (xsdo == NULL || w <= 0 || h <= 0) {
699
return;
700
}
701
702
arcW = ABS(arcW);
703
arcH = ABS(arcH);
704
if (arcW > w) {
705
arcW = w;
706
}
707
if (arcH > h) {
708
arcH = h;
709
}
710
711
if (arcW == 0 || arcH == 0) {
712
Java_sun_java2d_x11_X11Renderer_XFillRect(env, xr, pXSData, xgc,
713
x, y, w, h);
714
return;
715
}
716
717
halfW = (arcW / 2);
718
halfH = (arcH / 2);
719
720
/* clamp to short bounding box of round rectangle */
721
cx = CLAMP_TO_SHORT(x);
722
cy = CLAMP_TO_SHORT(y);
723
cxw = CLAMP_TO_SHORT(x + w);
724
cyh = CLAMP_TO_SHORT(y + h);
725
726
/* clamp to short coordinates of lines */
727
tx1 = CLAMP_TO_SHORT(x + halfW + 1);
728
tx2 = CLAMP_TO_SHORT(x + w - halfW - 1);
729
ty1 = CLAMP_TO_SHORT(y + halfH + 1);
730
ty2 = CLAMP_TO_SHORT(y + h - halfH - 1);
731
732
/*
733
* recalculate heightes and widthes of round parts
734
* to minimize distortions in visible area
735
*/
736
leftW = (tx1 - cx) * 2;
737
rightW = (cxw - tx2) * 2;
738
topH = (ty1 - cy) * 2;
739
bottomH = (cyh - ty2) * 2;
740
741
awt_drawArc(env, xsdo->drawable, (GC) xgc,
742
cx, cy, leftW, topH,
743
90, 90, JNI_TRUE);
744
awt_drawArc(env, xsdo->drawable, (GC) xgc,
745
cxw - rightW, cy, rightW, topH,
746
0, 90, JNI_TRUE);
747
awt_drawArc(env, xsdo->drawable, (GC) xgc,
748
cx, cyh - bottomH, leftW, bottomH,
749
180, 90, JNI_TRUE);
750
awt_drawArc(env, xsdo->drawable, (GC) xgc,
751
cxw - rightW, cyh - bottomH, rightW, bottomH,
752
270, 90, JNI_TRUE);
753
754
if (tx1 < tx2) {
755
if (cy < ty1) {
756
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,
757
tx1, cy, tx2 - tx1, ty1 - cy);
758
}
759
if (ty2 < cyh) {
760
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,
761
tx1, ty2, tx2 - tx1, cyh - ty2);
762
}
763
}
764
if (ty1 < ty2) {
765
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,
766
cx, ty1, cxw - cx, ty2 - ty1);
767
}
768
X11SD_DirectRenderNotify(env, xsdo);
769
#endif /* !HEADLESS */
770
}
771
772
/*
773
* Class: sun_java2d_x11_X11Renderer
774
* Method: XFillOval
775
* Signature: (IJIIII)V
776
*/
777
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillOval
778
(JNIEnv *env, jobject xr,
779
jlong pXSData, jlong xgc,
780
jint x, jint y, jint w, jint h)
781
{
782
#ifndef HEADLESS
783
X11SDOps *xsdo = (X11SDOps *) pXSData;
784
785
if (xsdo == NULL) {
786
return;
787
}
788
789
if (w < 3 || h < 3) {
790
/*
791
* Fix for 4205762 - 1x1 ovals do not draw on Ultra1, Creator3d
792
* (related to 4411814 on Windows platform)
793
* Most X11 servers drivers have poor rendering
794
* for thin ellipses and the rendering is most strikingly
795
* different from our theoretical arcs. Ideally we should
796
* trap all ovals less than some fairly large size and
797
* try to draw aesthetically pleasing ellipses, but that
798
* would require considerably more work to get the corresponding
799
* drawArc variants to match pixel for pixel.
800
* Thin ovals of girth 1 pixel are simple rectangles.
801
* Thin ovals of girth 2 pixels are simple rectangles with
802
* potentially smaller lengths. Determine the correct length
803
* by calculating .5*.5 + scaledlen*scaledlen == 1.0 which
804
* means that scaledlen is the sqrt(0.75). Scaledlen is
805
* relative to the true length (w or h) and needs to be
806
* adjusted by half a pixel in different ways for odd or
807
* even lengths.
808
*/
809
#define SQRT_3_4 0.86602540378443864676
810
if (w > 2 && h > 1) {
811
int adjw = (int) ((SQRT_3_4 * w - ((w&1)-1)) * 0.5);
812
adjw = adjw * 2 + (w&1);
813
x += (w-adjw)/2;
814
w = adjw;
815
} else if (h > 2 && w > 1) {
816
int adjh = (int) ((SQRT_3_4 * h - ((h&1)-1)) * 0.5);
817
adjh = adjh * 2 + (h&1);
818
y += (h-adjh)/2;
819
h = adjh;
820
}
821
#undef SQRT_3_4
822
if (w > 0 && h > 0) {
823
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc, x, y, w, h);
824
}
825
} else {
826
awt_drawArc(env, xsdo->drawable, (GC) xgc,
827
x, y, w, h, 0, 360, JNI_TRUE);
828
}
829
X11SD_DirectRenderNotify(env, xsdo);
830
#endif /* !HEADLESS */
831
}
832
833
/*
834
* Class: sun_java2d_x11_X11Renderer
835
* Method: XFillArc
836
* Signature: (IJIIIIII)V
837
*/
838
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillArc
839
(JNIEnv *env, jobject xr,
840
jlong pXSData, jlong xgc,
841
jint x, jint y, jint w, jint h,
842
jint angleStart, jint angleExtent)
843
{
844
#ifndef HEADLESS
845
X11SDOps *xsdo = (X11SDOps *) pXSData;
846
847
if (xsdo == NULL) {
848
return;
849
}
850
851
awt_drawArc(env, xsdo->drawable, (GC) xgc,
852
x, y, w, h, angleStart, angleExtent, JNI_TRUE);
853
X11SD_DirectRenderNotify(env, xsdo);
854
#endif /* !HEADLESS */
855
}
856
857
/*
858
* Class: sun_java2d_x11_X11Renderer
859
* Method: XFillPoly
860
* Signature: (IJII[I[II)V
861
*/
862
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillPoly
863
(JNIEnv *env, jobject xr,
864
jlong pXSData, jlong xgc,
865
jint transx, jint transy,
866
jintArray xcoordsArray, jintArray ycoordsArray, jint npoints)
867
{
868
#ifndef HEADLESS
869
XPoint pTmp[POLYTEMPSIZE], *points;
870
X11SDOps *xsdo = (X11SDOps *) pXSData;
871
872
if (xsdo == NULL) {
873
return;
874
}
875
876
if (JNU_IsNull(env, xcoordsArray) || JNU_IsNull(env, ycoordsArray)) {
877
JNU_ThrowNullPointerException(env, "coordinate array");
878
return;
879
}
880
if ((*env)->GetArrayLength(env, ycoordsArray) < npoints ||
881
(*env)->GetArrayLength(env, xcoordsArray) < npoints)
882
{
883
JNU_ThrowArrayIndexOutOfBoundsException(env, "coordinate array");
884
return;
885
}
886
887
if (npoints < 3) {
888
return;
889
}
890
891
points = transformPoints(env, xcoordsArray, ycoordsArray, transx, transy,
892
pTmp, (int *)&npoints, JNI_FALSE);
893
if (points != 0) {
894
if (npoints > 2) {
895
XFillPolygon(awt_display, xsdo->drawable, (GC) xgc,
896
points, npoints, Complex, CoordModeOrigin);
897
X11SD_DirectRenderNotify(env, xsdo);
898
}
899
if (points != pTmp) {
900
free(points);
901
}
902
}
903
#endif /* !HEADLESS */
904
}
905
906
/*
907
* Class: sun_java2d_x11_X11Renderer
908
* Method: XFillSpans
909
* Signature: (IJLsun/java2d/pipe/SpanIterator;JII)V
910
*/
911
JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillSpans
912
(JNIEnv *env, jobject xr,
913
jlong pXSData, jlong xgc,
914
jobject si, jlong pIterator,
915
jint transx, jint transy)
916
{
917
#ifndef HEADLESS
918
SpanIteratorFuncs *pFuncs = (SpanIteratorFuncs *) jlong_to_ptr(pIterator);
919
void *srData;
920
jint x, y, w, h;
921
jint spanbox[4];
922
X11SDOps *xsdo = (X11SDOps *) pXSData;
923
924
if (xsdo == NULL) {
925
return;
926
}
927
928
if (JNU_IsNull(env, si)) {
929
JNU_ThrowNullPointerException(env, "span iterator");
930
return;
931
}
932
if (pFuncs == NULL) {
933
JNU_ThrowNullPointerException(env, "native iterator not supplied");
934
return;
935
}
936
937
srData = (*pFuncs->open)(env, si);
938
while ((*pFuncs->nextSpan)(srData, spanbox)) {
939
x = spanbox[0] + transx;
940
y = spanbox[1] + transy;
941
w = spanbox[2] - spanbox[0];
942
h = spanbox[3] - spanbox[1];
943
XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,
944
CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),
945
CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h));
946
}
947
(*pFuncs->close)(env, srData);
948
X11SD_DirectRenderNotify(env, xsdo);
949
#endif /* !HEADLESS */
950
}
951
952
/*
953
* Class: sun_java2d_x11_X11Renderer
954
* Method: devCopyArea
955
* Signature: (Lsun/java2d/SurfaceData;IIIIII)V
956
*/
957
JNIEXPORT void JNICALL
958
Java_sun_java2d_x11_X11Renderer_devCopyArea
959
(JNIEnv *env, jobject xr,
960
jlong xsd, jlong gc,
961
jint srcx, jint srcy,
962
jint dstx, jint dsty,
963
jint width, jint height)
964
{
965
#ifndef HEADLESS
966
X11SDOps *xsdo;
967
GC xgc;
968
969
xsdo = (X11SDOps *)jlong_to_ptr(xsd);
970
if (xsdo == NULL) {
971
return;
972
}
973
974
xgc = (GC)gc;
975
if (xgc == NULL) {
976
return;
977
}
978
979
XCopyArea(awt_display, xsdo->drawable, xsdo->drawable, xgc,
980
srcx, srcy, width, height, dstx, dsty);
981
982
X11SD_DirectRenderNotify(env, xsdo);
983
#endif /* !HEADLESS */
984
}
985
986