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
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
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 }
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,
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
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 }
|
1 /*
2 * Copyright (c) 2000, 2016, 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
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 *) jlong_to_ptr(pXSData);
229
230 if (xsdo == NULL) {
231 return;
232 }
233
234 XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(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) jlong_to_ptr(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) jlong_to_ptr(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 *) jlong_to_ptr(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
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) jlong_to_ptr(xgc),
338 cx, cy, leftW, topH,
339 90, 90, JNI_FALSE);
340 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc),
341 cxw - rightW, cy, rightW, topH,
342 0, 90, JNI_FALSE);
343 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc),
344 cx, cyh - bottomH, leftW, bottomH,
345 180, 90, JNI_FALSE);
346 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(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) jlong_to_ptr(xgc),
352 tx1, cy, tx2, cy);
353 if (h > 0) {
354 XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc),
355 tx1, cyh, tx2, cyh);
356 }
357 }
358 if (ty1 <= ty2) {
359 XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc),
360 cx, ty1, cx, ty2);
361 if (w > 0) {
362 XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(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) jlong_to_ptr(xgc),
397 x, y, w+1, h+1);
398 }
399 } else {
400 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(pXSData);
420
421 if (xsdo == NULL) {
422 return;
423 }
424
425 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(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) jlong_to_ptr(xgc),
480 points[0].x, points[0].y,
481 points[1].x, points[1].y);
482 } else {
483 XDrawLines(awt_display, xsdo->drawable, (GC) jlong_to_ptr(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 }
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 *) jlong_to_ptr(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) jlong_to_ptr(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,
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 *) jlong_to_ptr(pXSData);
670
671 if (xsdo == NULL) {
672 return;
673 }
674
675 XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(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
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) jlong_to_ptr(xgc),
742 cx, cy, leftW, topH,
743 90, 90, JNI_TRUE);
744 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc),
745 cxw - rightW, cy, rightW, topH,
746 0, 90, JNI_TRUE);
747 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc),
748 cx, cyh - bottomH, leftW, bottomH,
749 180, 90, JNI_TRUE);
750 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(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) jlong_to_ptr(xgc),
757 tx1, cy, tx2 - tx1, ty1 - cy);
758 }
759 if (ty2 < cyh) {
760 XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc),
761 tx1, ty2, tx2 - tx1, cyh - ty2);
762 }
763 }
764 if (ty1 < ty2) {
765 XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(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) jlong_to_ptr(xgc), x, y, w, h);
824 }
825 } else {
826 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(pXSData);
846
847 if (xsdo == NULL) {
848 return;
849 }
850
851 awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(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 *) jlong_to_ptr(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) jlong_to_ptr(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 *) jlong_to_ptr(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) jlong_to_ptr(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) jlong_to_ptr(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 }
|