/* * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include "sun_java2d_x11_X11Renderer.h" #include "X11SurfaceData.h" #include "SpanIterator.h" #include "Trace.h" #include "ProcessPath.h" #include "GraphicsPrimitiveMgr.h" #include #ifndef HEADLESS #define POLYTEMPSIZE (int)(256 / sizeof(XPoint)) #define ABS(n) (((n) < 0) ? -(n) : (n)) #define MAX_SHORT 32767 #define MIN_SHORT (-32768) #define CLAMP_TO_SHORT(x) (((x) > MAX_SHORT) \ ? MAX_SHORT \ : ((x) < MIN_SHORT) \ ? MIN_SHORT \ : (x)) #define CLAMP_TO_USHORT(x) (((x) > 65535) ? 65535 : ((x) < 0) ? 0 : (x)) #define DF_MAX_XPNTS 256 typedef struct { Drawable drawable; GC gc; XPoint *pPoints; XPoint dfPoints[DF_MAX_XPNTS]; jint npoints; jint maxpoints; } XDrawHandlerData; #define XDHD_INIT(PTR, _GC, DRAWABLE) \ do { \ (PTR)->pPoints = (PTR)->dfPoints; \ (PTR)->npoints = 0; \ (PTR)->maxpoints = DF_MAX_XPNTS; \ (PTR)->gc = (_GC); \ (PTR)->drawable = (DRAWABLE); \ } while(0) #define XDHD_RESET(PTR) \ do { \ (PTR)->npoints = 0; \ } while(0) #define XDHD_ADD_POINT(PTR, X, Y) \ do { \ XPoint* _pnts = (PTR)->pPoints; \ jint _npnts = (PTR)->npoints; \ if (_npnts >= (PTR)->maxpoints) { \ jint newMax = (PTR)->maxpoints*2; \ if ((PTR)->pPoints == (PTR)->dfPoints) { \ (PTR)->pPoints = (XPoint*)malloc(newMax*sizeof(XPoint)); \ memcpy((PTR)->pPoints, _pnts, _npnts*sizeof(XPoint)); \ } else { \ (PTR)->pPoints = (XPoint*)realloc( \ _pnts, newMax*sizeof(XPoint)); \ } \ _pnts = (PTR)->pPoints; \ (PTR)->maxpoints = newMax; \ } \ _pnts += _npnts; \ _pnts->x = X; \ _pnts->y = Y; \ (PTR)->npoints = _npnts + 1; \ } while(0) #define XDHD_FREE_POINTS(PTR) \ do { \ if ((PTR)->pPoints != (PTR)->dfPoints) { \ free((PTR)->pPoints); \ } \ } while(0) static void awt_drawArc(JNIEnv * env, jint drawable, GC xgc, int x, int y, int w, int h, int startAngle, int endAngle, int filled) { int s, e; if (w < 0 || h < 0) { return; } if (endAngle >= 360 || endAngle <= -360) { s = 0; e = 360 * 64; } else { s = (startAngle % 360) * 64; e = endAngle * 64; } if (filled == 0) { XDrawArc(awt_display, drawable, xgc, x, y, w, h, s, e); } else { XFillArc(awt_display, drawable, xgc, x, y, w, h, s, e); } } /* * Copy vertices from xcoordsArray and ycoordsArray to a buffer * of XPoint structures, translating by transx and transy and * collapsing empty segments out of the list as we go. * The number of points to be converted should be guaranteed * to be more than 2 by the caller and is stored at *pNpoints. * The resulting number of uncollapsed unique translated vertices * will be stored back into the location *pNpoints. * The points pointer is guaranteed to be pointing to an area of * memory large enough for POLYTEMPSIZE points and a larger * area of memory is allocated (and returned) if that is not enough. */ static XPoint * transformPoints(JNIEnv * env, jintArray xcoordsArray, jintArray ycoordsArray, jint transx, jint transy, XPoint * points, int *pNpoints, int close) { int npoints = *pNpoints; jint *xcoords, *ycoords; xcoords = (jint *) (*env)->GetPrimitiveArrayCritical(env, xcoordsArray, NULL); if (xcoords == NULL) { return 0; } ycoords = (jint *) (*env)->GetPrimitiveArrayCritical(env, ycoordsArray, NULL); if (ycoords == NULL) { (*env)->ReleasePrimitiveArrayCritical(env, xcoordsArray, xcoords, JNI_ABORT); return 0; } if (close) { close = (xcoords[npoints - 1] != xcoords[0] || ycoords[npoints - 1] != ycoords[0]); if (close) { npoints++; } } if (npoints > POLYTEMPSIZE) { points = (XPoint *) malloc(sizeof(XPoint) * npoints); } if (points != NULL) { int in, out; int oldx = CLAMP_TO_SHORT(xcoords[0] + transx); int oldy = CLAMP_TO_SHORT(ycoords[0] + transy); points[0].x = oldx; points[0].y = oldy; if (close) { npoints--; } for (in = 1, out = 1; in < npoints; in++) { int newx = CLAMP_TO_SHORT(xcoords[in] + transx); int newy = CLAMP_TO_SHORT(ycoords[in] + transy); if (newx != oldx || newy != oldy) { points[out].x = newx; points[out].y = newy; out++; oldx = newx; oldy = newy; } } if (out == 1) { points[1].x = oldx; points[1].y = oldy; out = 2; } else if (close) { points[out++] = points[0]; } *pNpoints = out; } (*env)->ReleasePrimitiveArrayCritical(env, xcoordsArray, xcoords, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, ycoordsArray, ycoords, JNI_ABORT); return points; } #endif /* !HEADLESS */ /* * Class: sun_java2d_x11_X11Renderer * Method: XDrawLine * Signature: (IJIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawLine (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x1, jint y1, jint x2, jint y2) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), CLAMP_TO_SHORT(x1), CLAMP_TO_SHORT(y1), CLAMP_TO_SHORT(x2), CLAMP_TO_SHORT(y2)); X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XDrawRect * Signature: (IJIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawRect (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL || w < 0 || h < 0) { return; } if (w < 2 || h < 2) { /* REMIND: This optimization assumes thin lines. */ /* * This optimization not only simplifies the processing * of a particular degenerate case, but it protects against * the anomalies of various X11 implementations that draw * nothing for degenerate Polygons and Rectangles. */ XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y), CLAMP_TO_USHORT(w+1), CLAMP_TO_USHORT(h+1)); } else { XDrawRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y), CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h)); } X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XDrawRoundRect * Signature: (IJIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawRoundRect (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h, jint arcW, jint arcH) { #ifndef HEADLESS long ty1, ty2, tx1, tx2, cx, cy, cxw, cyh, halfW, halfH, leftW, rightW, topH, bottomH; X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL || w < 0 || h < 0) { return; } arcW = ABS(arcW); arcH = ABS(arcH); if (arcW > w) { arcW = w; } if (arcH > h) { arcH = h; } if (arcW == 0 || arcH == 0) { Java_sun_java2d_x11_X11Renderer_XDrawRect(env, xr, pXSData, xgc, x, y, w, h); return; } halfW = (arcW / 2); halfH = (arcH / 2); /* clamp to short bounding box of round rectangle */ cx = CLAMP_TO_SHORT(x); cy = CLAMP_TO_SHORT(y); cxw = CLAMP_TO_SHORT(x + w); cyh = CLAMP_TO_SHORT(y + h); /* clamp to short coordinates of lines */ tx1 = CLAMP_TO_SHORT(x + halfW + 1); tx2 = CLAMP_TO_SHORT(x + w - halfW - 1); ty1 = CLAMP_TO_SHORT(y + halfH + 1); ty2 = CLAMP_TO_SHORT(y + h - halfH - 1); /* * recalculate heightes and widthes of round parts * to minimize distortions in visible area */ leftW = (tx1 - cx) * 2; rightW = (cxw - tx2) * 2; topH = (ty1 - cy) * 2; bottomH = (cyh - ty2) * 2; awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cx, cy, leftW, topH, 90, 90, JNI_FALSE); awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cxw - rightW, cy, rightW, topH, 0, 90, JNI_FALSE); awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cx, cyh - bottomH, leftW, bottomH, 180, 90, JNI_FALSE); awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cxw - rightW, cyh - bottomH, rightW, bottomH, 270, 90, JNI_FALSE); if (tx1 <= tx2) { XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), tx1, cy, tx2, cy); if (h > 0) { XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), tx1, cyh, tx2, cyh); } } if (ty1 <= ty2) { XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), cx, ty1, cx, ty2); if (w > 0) { XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), cxw, ty1, cxw, ty2); } } X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XDrawOval * Signature: (IJIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawOval (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } if (w < 2 || h < 2) { /* * Fix for 4205762 - 1x1 ovals do not draw on Ultra1, Creator3d * (related to 4411814 on Windows platform) * Really small ovals degenerate to simple rectangles as they * have no curvature or enclosed area. Use XFillRectangle * for speed and to deal better with degenerate sizes. */ if (w >= 0 && h >= 0) { XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), x, y, w+1, h+1); } } else { awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), x, y, w, h, 0, 360, JNI_FALSE); } X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XDrawArc * Signature: (IJIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawArc (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h, jint angleStart, jint angleExtent) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), x, y, w, h, angleStart, angleExtent, JNI_FALSE); X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XDrawPoly * Signature: (IJII[I[IIZ)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawPoly (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint transx, jint transy, jintArray xcoordsArray, jintArray ycoordsArray, jint npoints, jboolean isclosed) { #ifndef HEADLESS XPoint pTmp[POLYTEMPSIZE], *points; X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } if (JNU_IsNull(env, xcoordsArray) || JNU_IsNull(env, ycoordsArray)) { JNU_ThrowNullPointerException(env, "coordinate array"); return; } if ((*env)->GetArrayLength(env, ycoordsArray) < npoints || (*env)->GetArrayLength(env, xcoordsArray) < npoints) { JNU_ThrowArrayIndexOutOfBoundsException(env, "coordinate array"); return; } if (npoints < 2) { return; } points = transformPoints(env, xcoordsArray, ycoordsArray, transx, transy, pTmp, (int *)&npoints, isclosed); if (points != 0) { if (npoints == 2) { /* * Some X11 implementations fail to draw anything for * simple 2 point polygons where the vertices are the * same point even though this violates the X11 * specification. For simplicity we will dispatch all * 2 point polygons through XDrawLine even if they are * non-degenerate as this may invoke less processing * down the line than a Poly primitive anyway. */ XDrawLine(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), points[0].x, points[0].y, points[1].x, points[1].y); } else { XDrawLines(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), points, npoints, CoordModeOrigin); } if (points != pTmp) { free(points); } X11SD_DirectRenderNotify(env, xsdo); } #endif /* !HEADLESS */ } static void storeLine(DrawHandler* hnd, jint x0, jint y0, jint x1, jint y1) { #ifndef HEADLESS XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData); XDHD_ADD_POINT(dhnd, x0, y0); XDHD_ADD_POINT(dhnd, x1, y1); #endif /* !HEADLESS */ } static void storePoint(DrawHandler* hnd, jint x0, jint y0) { #ifndef HEADLESS XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData); XDHD_ADD_POINT(dhnd, x0, y0); #endif /* !HEADLESS */ } static void drawSubPath(ProcessHandler* hnd) { #ifndef HEADLESS XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->dhnd->pData); XPoint *points = dhnd->pPoints; switch (dhnd->npoints) { case 0: /* No-op */ break; case 1: /* Draw the single pixel */ XFillRectangle(awt_display, dhnd->drawable, dhnd->gc, points[0].x, points[0].y, 1, 1); break; case 2: /* * The XDrawLines method for some X11 implementations * fails to draw anything for simple 2 point polygons * where the vertices are the same point even though * this violates the X11 specification. For simplicity * we will dispatch all 2 point polygons through XDrawLine * even if they are non-degenerate as this may invoke * less processing down the line than a poly primitive anyway. */ XDrawLine(awt_display, dhnd->drawable, dhnd->gc, points[0].x, points[0].y, points[1].x, points[1].y); break; default: /* Draw the entire polyline */ XDrawLines(awt_display, dhnd->drawable, dhnd->gc, points, dhnd->npoints, CoordModeOrigin); break; } XDHD_RESET(dhnd); #endif /* !HEADLESS */ } static void drawScanline(DrawHandler* hnd, jint x0, jint x1, jint y0) { #ifndef HEADLESS XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData); XDrawLine(awt_display, dhnd->drawable, dhnd->gc, x0, y0, x1, y0); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XDoPath * Signature: (Lsun/java2d/SunGraphics2D;JJIILjava/awt/geom/Path2D/Float;Z)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDoPath (JNIEnv *env, jobject self, jobject sg2d, jlong pXSData, jlong xgc, jint transX, jint transY, jobject p2df, jboolean isFill) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); jarray typesArray; jobject pointArray; jarray coordsArray; jint numTypes; jint fillRule; jint maxCoords; jbyte *types; jfloat *coords; XDrawHandlerData dHData; DrawHandler drawHandler = { NULL, NULL, NULL, MIN_SHORT, MIN_SHORT, MAX_SHORT, MAX_SHORT, 0, 0, 0, 0, NULL }; PHStroke stroke; jboolean ok = JNI_TRUE; if (xsdo == NULL) { return; } if (isFill) { fillRule = (*env)->GetIntField(env, p2df, path2DWindingRuleID); } typesArray = (jarray)(*env)->GetObjectField(env, p2df, path2DTypesID); coordsArray = (jarray)(*env)->GetObjectField(env, p2df, path2DFloatCoordsID); if (coordsArray == NULL) { JNU_ThrowNullPointerException(env, "coordinates array"); return; } numTypes = (*env)->GetIntField(env, p2df, path2DNumTypesID); if ((*env)->GetArrayLength(env, typesArray) < numTypes) { JNU_ThrowArrayIndexOutOfBoundsException(env, "types array"); return; } XDHD_INIT(&dHData, (GC) jlong_to_ptr(xgc), xsdo->drawable); drawHandler.pData = &dHData; stroke = (((*env)->GetIntField(env, sg2d, sg2dStrokeHintID) == sunHints_INTVAL_STROKE_PURE) ? PH_STROKE_PURE : PH_STROKE_DEFAULT); maxCoords = (*env)->GetArrayLength(env, coordsArray); coords = (jfloat*) (*env)->GetPrimitiveArrayCritical(env, coordsArray, NULL); if (coords != NULL) { types = (jbyte*) (*env)->GetPrimitiveArrayCritical(env, typesArray, NULL); if (types != NULL) { if (isFill) { drawHandler.pDrawScanline = &drawScanline; ok = doFillPath(&drawHandler, transX, transY, coords, maxCoords, types, numTypes, stroke, fillRule); } else { drawHandler.pDrawLine = &storeLine; drawHandler.pDrawPixel = &storePoint; ok = doDrawPath(&drawHandler, &drawSubPath, transX, transY, coords, maxCoords, types, numTypes, stroke); } (*env)->ReleasePrimitiveArrayCritical(env, typesArray, types, JNI_ABORT); } (*env)->ReleasePrimitiveArrayCritical(env, coordsArray, coords, JNI_ABORT); if (!ok) { JNU_ThrowArrayIndexOutOfBoundsException(env, "coords array"); } } XDHD_FREE_POINTS(&dHData); X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XFillRect * Signature: (IJIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillRect (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y), CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h)); X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XFillRoundRect * Signature: (IJIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillRoundRect (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h, jint arcW, jint arcH) { #ifndef HEADLESS long ty1, ty2, tx1, tx2, cx, cy, cxw, cyh, halfW, halfH, leftW, rightW, topH, bottomH; X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL || w <= 0 || h <= 0) { return; } arcW = ABS(arcW); arcH = ABS(arcH); if (arcW > w) { arcW = w; } if (arcH > h) { arcH = h; } if (arcW == 0 || arcH == 0) { Java_sun_java2d_x11_X11Renderer_XFillRect(env, xr, pXSData, xgc, x, y, w, h); return; } halfW = (arcW / 2); halfH = (arcH / 2); /* clamp to short bounding box of round rectangle */ cx = CLAMP_TO_SHORT(x); cy = CLAMP_TO_SHORT(y); cxw = CLAMP_TO_SHORT(x + w); cyh = CLAMP_TO_SHORT(y + h); /* clamp to short coordinates of lines */ tx1 = CLAMP_TO_SHORT(x + halfW + 1); tx2 = CLAMP_TO_SHORT(x + w - halfW - 1); ty1 = CLAMP_TO_SHORT(y + halfH + 1); ty2 = CLAMP_TO_SHORT(y + h - halfH - 1); /* * recalculate heightes and widthes of round parts * to minimize distortions in visible area */ leftW = (tx1 - cx) * 2; rightW = (cxw - tx2) * 2; topH = (ty1 - cy) * 2; bottomH = (cyh - ty2) * 2; awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cx, cy, leftW, topH, 90, 90, JNI_TRUE); awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cxw - rightW, cy, rightW, topH, 0, 90, JNI_TRUE); awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cx, cyh - bottomH, leftW, bottomH, 180, 90, JNI_TRUE); awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), cxw - rightW, cyh - bottomH, rightW, bottomH, 270, 90, JNI_TRUE); if (tx1 < tx2) { if (cy < ty1) { XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), tx1, cy, tx2 - tx1, ty1 - cy); } if (ty2 < cyh) { XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), tx1, ty2, tx2 - tx1, cyh - ty2); } } if (ty1 < ty2) { XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), cx, ty1, cxw - cx, ty2 - ty1); } X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XFillOval * Signature: (IJIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillOval (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } if (w < 3 || h < 3) { /* * Fix for 4205762 - 1x1 ovals do not draw on Ultra1, Creator3d * (related to 4411814 on Windows platform) * Most X11 servers drivers have poor rendering * for thin ellipses and the rendering is most strikingly * different from our theoretical arcs. Ideally we should * trap all ovals less than some fairly large size and * try to draw aesthetically pleasing ellipses, but that * would require considerably more work to get the corresponding * drawArc variants to match pixel for pixel. * Thin ovals of girth 1 pixel are simple rectangles. * Thin ovals of girth 2 pixels are simple rectangles with * potentially smaller lengths. Determine the correct length * by calculating .5*.5 + scaledlen*scaledlen == 1.0 which * means that scaledlen is the sqrt(0.75). Scaledlen is * relative to the true length (w or h) and needs to be * adjusted by half a pixel in different ways for odd or * even lengths. */ #define SQRT_3_4 0.86602540378443864676 if (w > 2 && h > 1) { int adjw = (int) ((SQRT_3_4 * w - ((w&1)-1)) * 0.5); adjw = adjw * 2 + (w&1); x += (w-adjw)/2; w = adjw; } else if (h > 2 && w > 1) { int adjh = (int) ((SQRT_3_4 * h - ((h&1)-1)) * 0.5); adjh = adjh * 2 + (h&1); y += (h-adjh)/2; h = adjh; } #undef SQRT_3_4 if (w > 0 && h > 0) { XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), x, y, w, h); } } else { awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), x, y, w, h, 0, 360, JNI_TRUE); } X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XFillArc * Signature: (IJIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillArc (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint x, jint y, jint w, jint h, jint angleStart, jint angleExtent) { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } awt_drawArc(env, xsdo->drawable, (GC) jlong_to_ptr(xgc), x, y, w, h, angleStart, angleExtent, JNI_TRUE); X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XFillPoly * Signature: (IJII[I[II)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillPoly (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jint transx, jint transy, jintArray xcoordsArray, jintArray ycoordsArray, jint npoints) { #ifndef HEADLESS XPoint pTmp[POLYTEMPSIZE], *points; X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } if (JNU_IsNull(env, xcoordsArray) || JNU_IsNull(env, ycoordsArray)) { JNU_ThrowNullPointerException(env, "coordinate array"); return; } if ((*env)->GetArrayLength(env, ycoordsArray) < npoints || (*env)->GetArrayLength(env, xcoordsArray) < npoints) { JNU_ThrowArrayIndexOutOfBoundsException(env, "coordinate array"); return; } if (npoints < 3) { return; } points = transformPoints(env, xcoordsArray, ycoordsArray, transx, transy, pTmp, (int *)&npoints, JNI_FALSE); if (points != 0) { if (npoints > 2) { XFillPolygon(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), points, npoints, Complex, CoordModeOrigin); X11SD_DirectRenderNotify(env, xsdo); } if (points != pTmp) { free(points); } } #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: XFillSpans * Signature: (IJLsun/java2d/pipe/SpanIterator;JII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillSpans (JNIEnv *env, jobject xr, jlong pXSData, jlong xgc, jobject si, jlong pIterator, jint transx, jint transy) { #ifndef HEADLESS SpanIteratorFuncs *pFuncs = (SpanIteratorFuncs *) jlong_to_ptr(pIterator); void *srData; jint x, y, w, h; jint spanbox[4]; X11SDOps *xsdo = (X11SDOps *) jlong_to_ptr(pXSData); if (xsdo == NULL) { return; } if (JNU_IsNull(env, si)) { JNU_ThrowNullPointerException(env, "span iterator"); return; } if (pFuncs == NULL) { JNU_ThrowNullPointerException(env, "native iterator not supplied"); return; } srData = (*pFuncs->open)(env, si); while ((*pFuncs->nextSpan)(srData, spanbox)) { x = spanbox[0] + transx; y = spanbox[1] + transy; w = spanbox[2] - spanbox[0]; h = spanbox[3] - spanbox[1]; XFillRectangle(awt_display, xsdo->drawable, (GC) jlong_to_ptr(xgc), CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y), CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h)); } (*pFuncs->close)(env, srData); X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ } /* * Class: sun_java2d_x11_X11Renderer * Method: devCopyArea * Signature: (Lsun/java2d/SurfaceData;IIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_devCopyArea (JNIEnv *env, jobject xr, jlong xsd, jlong gc, jint srcx, jint srcy, jint dstx, jint dsty, jint width, jint height) { #ifndef HEADLESS X11SDOps *xsdo; GC xgc; xsdo = (X11SDOps *)jlong_to_ptr(xsd); if (xsdo == NULL) { return; } xgc = (GC) jlong_to_ptr(gc); if (xgc == NULL) { return; } XCopyArea(awt_display, xsdo->drawable, xsdo->drawable, xgc, srcx, srcy, width, height, dstx, dsty); X11SD_DirectRenderNotify(env, xsdo); #endif /* !HEADLESS */ }