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