Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/java2d/x11/X11Renderer.c
32288 views
/*1* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "sun_java2d_x11_X11Renderer.h"2627#include "X11SurfaceData.h"28#include "SpanIterator.h"29#include "Trace.h"30#include "ProcessPath.h"31#include "GraphicsPrimitiveMgr.h"323334#include <jlong.h>3536#ifndef HEADLESS37#define POLYTEMPSIZE (int)(256 / sizeof(XPoint))38#define ABS(n) (((n) < 0) ? -(n) : (n))3940#define MAX_SHORT 3276741#define MIN_SHORT (-32768)4243#define CLAMP_TO_SHORT(x) (((x) > MAX_SHORT) \44? MAX_SHORT \45: ((x) < MIN_SHORT) \46? MIN_SHORT \47: (x))4849#define CLAMP_TO_USHORT(x) (((x) > 65535) ? 65535 : ((x) < 0) ? 0 : (x))5051#define DF_MAX_XPNTS 2565253typedef struct {54Drawable drawable;55GC gc;56XPoint *pPoints;57XPoint dfPoints[DF_MAX_XPNTS];58jint npoints;59jint maxpoints;60} XDrawHandlerData;6162#define XDHD_INIT(PTR, _GC, DRAWABLE) \63do { \64(PTR)->pPoints = (PTR)->dfPoints; \65(PTR)->npoints = 0; \66(PTR)->maxpoints = DF_MAX_XPNTS; \67(PTR)->gc = (_GC); \68(PTR)->drawable = (DRAWABLE); \69} while(0)7071#define XDHD_RESET(PTR) \72do { \73(PTR)->npoints = 0; \74} while(0)757677#define XDHD_ADD_POINT(PTR, X, Y) \78do { \79XPoint* _pnts = (PTR)->pPoints; \80jint _npnts = (PTR)->npoints; \81if (_npnts >= (PTR)->maxpoints) { \82jint newMax = (PTR)->maxpoints*2; \83if ((PTR)->pPoints == (PTR)->dfPoints) { \84(PTR)->pPoints = (XPoint*)malloc(newMax*sizeof(XPoint)); \85memcpy((PTR)->pPoints, _pnts, _npnts*sizeof(XPoint)); \86} else { \87(PTR)->pPoints = (XPoint*)realloc( \88_pnts, newMax*sizeof(XPoint)); \89} \90_pnts = (PTR)->pPoints; \91(PTR)->maxpoints = newMax; \92} \93_pnts += _npnts; \94_pnts->x = X; \95_pnts->y = Y; \96(PTR)->npoints = _npnts + 1; \97} while(0)9899#define XDHD_FREE_POINTS(PTR) \100do { \101if ((PTR)->pPoints != (PTR)->dfPoints) { \102free((PTR)->pPoints); \103} \104} while(0)105106107static void108awt_drawArc(JNIEnv * env, jint drawable, GC xgc,109int x, int y, int w, int h,110int startAngle, int endAngle,111int filled)112{113int s, e;114115if (w < 0 || h < 0) {116return;117}118if (endAngle >= 360 || endAngle <= -360) {119s = 0;120e = 360 * 64;121} else {122s = (startAngle % 360) * 64;123e = endAngle * 64;124}125if (filled == 0) {126XDrawArc(awt_display, drawable, xgc, x, y, w, h, s, e);127} else {128XFillArc(awt_display, drawable, xgc, x, y, w, h, s, e);129}130}131132/*133* Copy vertices from xcoordsArray and ycoordsArray to a buffer134* of XPoint structures, translating by transx and transy and135* collapsing empty segments out of the list as we go.136* The number of points to be converted should be guaranteed137* to be more than 2 by the caller and is stored at *pNpoints.138* The resulting number of uncollapsed unique translated vertices139* will be stored back into the location *pNpoints.140* The points pointer is guaranteed to be pointing to an area of141* memory large enough for POLYTEMPSIZE points and a larger142* area of memory is allocated (and returned) if that is not enough.143*/144static XPoint *145transformPoints(JNIEnv * env,146jintArray xcoordsArray, jintArray ycoordsArray,147jint transx, jint transy,148XPoint * points, int *pNpoints, int close)149{150int npoints = *pNpoints;151jint *xcoords, *ycoords;152153xcoords = (jint *)154(*env)->GetPrimitiveArrayCritical(env, xcoordsArray, NULL);155if (xcoords == NULL) {156return 0;157}158159ycoords = (jint *)160(*env)->GetPrimitiveArrayCritical(env, ycoordsArray, NULL);161if (ycoords == NULL) {162(*env)->ReleasePrimitiveArrayCritical(env, xcoordsArray, xcoords,163JNI_ABORT);164return 0;165}166167if (close) {168close = (xcoords[npoints - 1] != xcoords[0] ||169ycoords[npoints - 1] != ycoords[0]);170if (close) {171npoints++;172}173}174if (npoints > POLYTEMPSIZE) {175points = (XPoint *) malloc(sizeof(XPoint) * npoints);176}177if (points != NULL) {178int in, out;179int oldx = CLAMP_TO_SHORT(xcoords[0] + transx);180int oldy = CLAMP_TO_SHORT(ycoords[0] + transy);181points[0].x = oldx;182points[0].y = oldy;183if (close) {184npoints--;185}186for (in = 1, out = 1; in < npoints; in++) {187int newx = CLAMP_TO_SHORT(xcoords[in] + transx);188int newy = CLAMP_TO_SHORT(ycoords[in] + transy);189if (newx != oldx || newy != oldy) {190points[out].x = newx;191points[out].y = newy;192out++;193oldx = newx;194oldy = newy;195}196}197if (out == 1) {198points[1].x = oldx;199points[1].y = oldy;200out = 2;201} else if (close) {202points[out++] = points[0];203}204*pNpoints = out;205}206207(*env)->ReleasePrimitiveArrayCritical(env, xcoordsArray, xcoords,208JNI_ABORT);209(*env)->ReleasePrimitiveArrayCritical(env, ycoordsArray, ycoords,210JNI_ABORT);211212return points;213}214#endif /* !HEADLESS */215216/*217* Class: sun_java2d_x11_X11Renderer218* Method: XDrawLine219* Signature: (IJIIII)V220*/221JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawLine222(JNIEnv *env, jobject xr,223jlong pXSData, jlong xgc,224jint x1, jint y1, jint x2, jint y2)225{226#ifndef HEADLESS227X11SDOps *xsdo = (X11SDOps *) pXSData;228229if (xsdo == NULL) {230return;231}232233XDrawLine(awt_display, xsdo->drawable, (GC) xgc,234CLAMP_TO_SHORT(x1), CLAMP_TO_SHORT(y1),235CLAMP_TO_SHORT(x2), CLAMP_TO_SHORT(y2));236X11SD_DirectRenderNotify(env, xsdo);237#endif /* !HEADLESS */238}239240/*241* Class: sun_java2d_x11_X11Renderer242* Method: XDrawRect243* Signature: (IJIIII)V244*/245JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawRect246(JNIEnv *env, jobject xr,247jlong pXSData, jlong xgc,248jint x, jint y, jint w, jint h)249{250#ifndef HEADLESS251X11SDOps *xsdo = (X11SDOps *) pXSData;252253if (xsdo == NULL || w < 0 || h < 0) {254return;255}256257if (w < 2 || h < 2) {258/* REMIND: This optimization assumes thin lines. */259/*260* This optimization not only simplifies the processing261* of a particular degenerate case, but it protects against262* the anomalies of various X11 implementations that draw263* nothing for degenerate Polygons and Rectangles.264*/265XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,266CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),267CLAMP_TO_USHORT(w+1), CLAMP_TO_USHORT(h+1));268} else {269XDrawRectangle(awt_display, xsdo->drawable, (GC) xgc,270CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),271CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h));272}273X11SD_DirectRenderNotify(env, xsdo);274#endif /* !HEADLESS */275}276277/*278* Class: sun_java2d_x11_X11Renderer279* Method: XDrawRoundRect280* Signature: (IJIIIIII)V281*/282JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawRoundRect283(JNIEnv *env, jobject xr,284jlong pXSData, jlong xgc,285jint x, jint y, jint w, jint h,286jint arcW, jint arcH)287{288#ifndef HEADLESS289long ty1, ty2, tx1, tx2, cx, cy, cxw, cyh,290halfW, halfH, leftW, rightW, topH, bottomH;291X11SDOps *xsdo = (X11SDOps *) pXSData;292293if (xsdo == NULL || w < 0 || h < 0) {294return;295}296297arcW = ABS(arcW);298arcH = ABS(arcH);299if (arcW > w) {300arcW = w;301}302if (arcH > h) {303arcH = h;304}305306if (arcW == 0 || arcH == 0) {307Java_sun_java2d_x11_X11Renderer_XDrawRect(env, xr, pXSData, xgc,308x, y, w, h);309return;310}311312halfW = (arcW / 2);313halfH = (arcH / 2);314315/* clamp to short bounding box of round rectangle */316cx = CLAMP_TO_SHORT(x);317cy = CLAMP_TO_SHORT(y);318cxw = CLAMP_TO_SHORT(x + w);319cyh = CLAMP_TO_SHORT(y + h);320321/* clamp to short coordinates of lines */322tx1 = CLAMP_TO_SHORT(x + halfW + 1);323tx2 = CLAMP_TO_SHORT(x + w - halfW - 1);324ty1 = CLAMP_TO_SHORT(y + halfH + 1);325ty2 = CLAMP_TO_SHORT(y + h - halfH - 1);326327/*328* recalculate heightes and widthes of round parts329* to minimize distortions in visible area330*/331leftW = (tx1 - cx) * 2;332rightW = (cxw - tx2) * 2;333topH = (ty1 - cy) * 2;334bottomH = (cyh - ty2) * 2;335336awt_drawArc(env, xsdo->drawable, (GC) xgc,337cx, cy, leftW, topH,33890, 90, JNI_FALSE);339awt_drawArc(env, xsdo->drawable, (GC) xgc,340cxw - rightW, cy, rightW, topH,3410, 90, JNI_FALSE);342awt_drawArc(env, xsdo->drawable, (GC) xgc,343cx, cyh - bottomH, leftW, bottomH,344180, 90, JNI_FALSE);345awt_drawArc(env, xsdo->drawable, (GC) xgc,346cxw - rightW, cyh - bottomH, rightW, bottomH,347270, 90, JNI_FALSE);348349if (tx1 <= tx2) {350XDrawLine(awt_display, xsdo->drawable, (GC) xgc,351tx1, cy, tx2, cy);352if (h > 0) {353XDrawLine(awt_display, xsdo->drawable, (GC) xgc,354tx1, cyh, tx2, cyh);355}356}357if (ty1 <= ty2) {358XDrawLine(awt_display, xsdo->drawable, (GC) xgc,359cx, ty1, cx, ty2);360if (w > 0) {361XDrawLine(awt_display, xsdo->drawable, (GC) xgc,362cxw, ty1, cxw, ty2);363}364}365X11SD_DirectRenderNotify(env, xsdo);366#endif /* !HEADLESS */367}368369/*370* Class: sun_java2d_x11_X11Renderer371* Method: XDrawOval372* Signature: (IJIIII)V373*/374JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawOval375(JNIEnv *env, jobject xr,376jlong pXSData, jlong xgc,377jint x, jint y, jint w, jint h)378{379#ifndef HEADLESS380X11SDOps *xsdo = (X11SDOps *) pXSData;381382if (xsdo == NULL) {383return;384}385386if (w < 2 || h < 2) {387/*388* Fix for 4205762 - 1x1 ovals do not draw on Ultra1, Creator3d389* (related to 4411814 on Windows platform)390* Really small ovals degenerate to simple rectangles as they391* have no curvature or enclosed area. Use XFillRectangle392* for speed and to deal better with degenerate sizes.393*/394if (w >= 0 && h >= 0) {395XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,396x, y, w+1, h+1);397}398} else {399awt_drawArc(env, xsdo->drawable, (GC) xgc,400x, y, w, h, 0, 360, JNI_FALSE);401}402X11SD_DirectRenderNotify(env, xsdo);403#endif /* !HEADLESS */404}405406/*407* Class: sun_java2d_x11_X11Renderer408* Method: XDrawArc409* Signature: (IJIIIIII)V410*/411JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawArc412(JNIEnv *env, jobject xr,413jlong pXSData, jlong xgc,414jint x, jint y, jint w, jint h,415jint angleStart, jint angleExtent)416{417#ifndef HEADLESS418X11SDOps *xsdo = (X11SDOps *) pXSData;419420if (xsdo == NULL) {421return;422}423424awt_drawArc(env, xsdo->drawable, (GC) xgc,425x, y, w, h, angleStart, angleExtent, JNI_FALSE);426X11SD_DirectRenderNotify(env, xsdo);427#endif /* !HEADLESS */428}429430/*431* Class: sun_java2d_x11_X11Renderer432* Method: XDrawPoly433* Signature: (IJII[I[IIZ)V434*/435JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XDrawPoly436(JNIEnv *env, jobject xr,437jlong pXSData, jlong xgc,438jint transx, jint transy,439jintArray xcoordsArray, jintArray ycoordsArray, jint npoints,440jboolean isclosed)441{442#ifndef HEADLESS443XPoint pTmp[POLYTEMPSIZE], *points;444X11SDOps *xsdo = (X11SDOps *) pXSData;445446if (xsdo == NULL) {447return;448}449450if (JNU_IsNull(env, xcoordsArray) || JNU_IsNull(env, ycoordsArray)) {451JNU_ThrowNullPointerException(env, "coordinate array");452return;453}454if ((*env)->GetArrayLength(env, ycoordsArray) < npoints ||455(*env)->GetArrayLength(env, xcoordsArray) < npoints)456{457JNU_ThrowArrayIndexOutOfBoundsException(env, "coordinate array");458return;459}460461if (npoints < 2) {462return;463}464465points = transformPoints(env, xcoordsArray, ycoordsArray, transx, transy,466pTmp, (int *)&npoints, isclosed);467if (points != 0) {468if (npoints == 2) {469/*470* Some X11 implementations fail to draw anything for471* simple 2 point polygons where the vertices are the472* same point even though this violates the X11473* specification. For simplicity we will dispatch all474* 2 point polygons through XDrawLine even if they are475* non-degenerate as this may invoke less processing476* down the line than a Poly primitive anyway.477*/478XDrawLine(awt_display, xsdo->drawable, (GC) xgc,479points[0].x, points[0].y,480points[1].x, points[1].y);481} else {482XDrawLines(awt_display, xsdo->drawable, (GC) xgc,483points, npoints, CoordModeOrigin);484}485if (points != pTmp) {486free(points);487}488X11SD_DirectRenderNotify(env, xsdo);489}490#endif /* !HEADLESS */491}492493static void storeLine(DrawHandler* hnd,494jint x0, jint y0, jint x1, jint y1)495{496#ifndef HEADLESS497XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData);498499XDHD_ADD_POINT(dhnd, x0, y0);500XDHD_ADD_POINT(dhnd, x1, y1);501#endif /* !HEADLESS */502}503504static void storePoint(DrawHandler* hnd, jint x0, jint y0) {505#ifndef HEADLESS506XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData);507508XDHD_ADD_POINT(dhnd, x0, y0);509#endif /* !HEADLESS */510}511512static void drawSubPath(ProcessHandler* hnd) {513#ifndef HEADLESS514XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->dhnd->pData);515XPoint *points = dhnd->pPoints;516517switch (dhnd->npoints) {518case 0:519/* No-op */520break;521case 1:522/* Draw the single pixel */523XFillRectangle(awt_display, dhnd->drawable, dhnd->gc,524points[0].x, points[0].y, 1, 1);525break;526case 2:527/*528* The XDrawLines method for some X11 implementations529* fails to draw anything for simple 2 point polygons530* where the vertices are the same point even though531* this violates the X11 specification. For simplicity532* we will dispatch all 2 point polygons through XDrawLine533* even if they are non-degenerate as this may invoke534* less processing down the line than a poly primitive anyway.535*/536XDrawLine(awt_display, dhnd->drawable, dhnd->gc,537points[0].x, points[0].y,538points[1].x, points[1].y);539break;540default:541/* Draw the entire polyline */542XDrawLines(awt_display, dhnd->drawable, dhnd->gc, points,543dhnd->npoints, CoordModeOrigin);544break;545}546547XDHD_RESET(dhnd);548#endif /* !HEADLESS */549}550551static void drawScanline(DrawHandler* hnd, jint x0, jint x1, jint y0)552{553#ifndef HEADLESS554XDrawHandlerData* dhnd = (XDrawHandlerData*)(hnd->pData);555556XDrawLine(awt_display, dhnd->drawable, dhnd->gc, x0, y0, x1, y0);557#endif /* !HEADLESS */558}559560/*561* Class: sun_java2d_x11_X11Renderer562* Method: XDoPath563* Signature: (Lsun/java2d/SunGraphics2D;JJIILjava/awt/geom/Path2D/Float;Z)V564*/565JNIEXPORT void JNICALL566Java_sun_java2d_x11_X11Renderer_XDoPath567(JNIEnv *env, jobject self, jobject sg2d, jlong pXSData, jlong xgc,568jint transX, jint transY, jobject p2df, jboolean isFill)569{570#ifndef HEADLESS571X11SDOps *xsdo = (X11SDOps *) pXSData;572jarray typesArray;573jobject pointArray;574jarray coordsArray;575jint numTypes;576jint fillRule;577jint maxCoords;578jbyte *types;579jfloat *coords;580XDrawHandlerData dHData;581DrawHandler drawHandler = {582NULL, NULL, NULL,583MIN_SHORT, MIN_SHORT, MAX_SHORT, MAX_SHORT,5840, 0, 0, 0,585NULL586};587PHStroke stroke;588jboolean ok = JNI_TRUE;589590if (xsdo == NULL) {591return;592}593594if (isFill) {595fillRule = (*env)->GetIntField(env, p2df, path2DWindingRuleID);596}597598typesArray = (jarray)(*env)->GetObjectField(env, p2df, path2DTypesID);599coordsArray = (jarray)(*env)->GetObjectField(env, p2df,600path2DFloatCoordsID);601if (coordsArray == NULL) {602JNU_ThrowNullPointerException(env, "coordinates array");603return;604}605numTypes = (*env)->GetIntField(env, p2df, path2DNumTypesID);606if ((*env)->GetArrayLength(env, typesArray) < numTypes) {607JNU_ThrowArrayIndexOutOfBoundsException(env, "types array");608return;609}610611XDHD_INIT(&dHData, (GC)xgc, xsdo->drawable);612drawHandler.pData = &dHData;613614stroke = (((*env)->GetIntField(env, sg2d, sg2dStrokeHintID) ==615sunHints_INTVAL_STROKE_PURE)616? PH_STROKE_PURE617: PH_STROKE_DEFAULT);618619maxCoords = (*env)->GetArrayLength(env, coordsArray);620coords = (jfloat*)621(*env)->GetPrimitiveArrayCritical(env, coordsArray, NULL);622if (coords != NULL) {623types = (jbyte*)624(*env)->GetPrimitiveArrayCritical(env, typesArray, NULL);625if (types != NULL) {626if (isFill) {627drawHandler.pDrawScanline = &drawScanline;628ok = doFillPath(&drawHandler,629transX, transY,630coords, maxCoords,631types, numTypes,632stroke, fillRule);633} else {634drawHandler.pDrawLine = &storeLine;635drawHandler.pDrawPixel = &storePoint;636ok = doDrawPath(&drawHandler, &drawSubPath,637transX, transY,638coords, maxCoords,639types, numTypes,640stroke);641}642(*env)->ReleasePrimitiveArrayCritical(env, typesArray, types,643JNI_ABORT);644}645(*env)->ReleasePrimitiveArrayCritical(env, coordsArray, coords,646JNI_ABORT);647if (!ok) {648JNU_ThrowArrayIndexOutOfBoundsException(env, "coords array");649}650}651652XDHD_FREE_POINTS(&dHData);653X11SD_DirectRenderNotify(env, xsdo);654#endif /* !HEADLESS */655}656657/*658* Class: sun_java2d_x11_X11Renderer659* Method: XFillRect660* Signature: (IJIIII)V661*/662JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillRect663(JNIEnv *env, jobject xr,664jlong pXSData, jlong xgc,665jint x, jint y, jint w, jint h)666{667#ifndef HEADLESS668X11SDOps *xsdo = (X11SDOps *) pXSData;669670if (xsdo == NULL) {671return;672}673674XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,675CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),676CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h));677X11SD_DirectRenderNotify(env, xsdo);678#endif /* !HEADLESS */679}680681/*682* Class: sun_java2d_x11_X11Renderer683* Method: XFillRoundRect684* Signature: (IJIIIIII)V685*/686JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillRoundRect687(JNIEnv *env, jobject xr,688jlong pXSData, jlong xgc,689jint x, jint y, jint w, jint h,690jint arcW, jint arcH)691{692#ifndef HEADLESS693long ty1, ty2, tx1, tx2, cx, cy, cxw, cyh,694halfW, halfH, leftW, rightW, topH, bottomH;695X11SDOps *xsdo = (X11SDOps *) pXSData;696697if (xsdo == NULL || w <= 0 || h <= 0) {698return;699}700701arcW = ABS(arcW);702arcH = ABS(arcH);703if (arcW > w) {704arcW = w;705}706if (arcH > h) {707arcH = h;708}709710if (arcW == 0 || arcH == 0) {711Java_sun_java2d_x11_X11Renderer_XFillRect(env, xr, pXSData, xgc,712x, y, w, h);713return;714}715716halfW = (arcW / 2);717halfH = (arcH / 2);718719/* clamp to short bounding box of round rectangle */720cx = CLAMP_TO_SHORT(x);721cy = CLAMP_TO_SHORT(y);722cxw = CLAMP_TO_SHORT(x + w);723cyh = CLAMP_TO_SHORT(y + h);724725/* clamp to short coordinates of lines */726tx1 = CLAMP_TO_SHORT(x + halfW + 1);727tx2 = CLAMP_TO_SHORT(x + w - halfW - 1);728ty1 = CLAMP_TO_SHORT(y + halfH + 1);729ty2 = CLAMP_TO_SHORT(y + h - halfH - 1);730731/*732* recalculate heightes and widthes of round parts733* to minimize distortions in visible area734*/735leftW = (tx1 - cx) * 2;736rightW = (cxw - tx2) * 2;737topH = (ty1 - cy) * 2;738bottomH = (cyh - ty2) * 2;739740awt_drawArc(env, xsdo->drawable, (GC) xgc,741cx, cy, leftW, topH,74290, 90, JNI_TRUE);743awt_drawArc(env, xsdo->drawable, (GC) xgc,744cxw - rightW, cy, rightW, topH,7450, 90, JNI_TRUE);746awt_drawArc(env, xsdo->drawable, (GC) xgc,747cx, cyh - bottomH, leftW, bottomH,748180, 90, JNI_TRUE);749awt_drawArc(env, xsdo->drawable, (GC) xgc,750cxw - rightW, cyh - bottomH, rightW, bottomH,751270, 90, JNI_TRUE);752753if (tx1 < tx2) {754if (cy < ty1) {755XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,756tx1, cy, tx2 - tx1, ty1 - cy);757}758if (ty2 < cyh) {759XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,760tx1, ty2, tx2 - tx1, cyh - ty2);761}762}763if (ty1 < ty2) {764XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,765cx, ty1, cxw - cx, ty2 - ty1);766}767X11SD_DirectRenderNotify(env, xsdo);768#endif /* !HEADLESS */769}770771/*772* Class: sun_java2d_x11_X11Renderer773* Method: XFillOval774* Signature: (IJIIII)V775*/776JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillOval777(JNIEnv *env, jobject xr,778jlong pXSData, jlong xgc,779jint x, jint y, jint w, jint h)780{781#ifndef HEADLESS782X11SDOps *xsdo = (X11SDOps *) pXSData;783784if (xsdo == NULL) {785return;786}787788if (w < 3 || h < 3) {789/*790* Fix for 4205762 - 1x1 ovals do not draw on Ultra1, Creator3d791* (related to 4411814 on Windows platform)792* Most X11 servers drivers have poor rendering793* for thin ellipses and the rendering is most strikingly794* different from our theoretical arcs. Ideally we should795* trap all ovals less than some fairly large size and796* try to draw aesthetically pleasing ellipses, but that797* would require considerably more work to get the corresponding798* drawArc variants to match pixel for pixel.799* Thin ovals of girth 1 pixel are simple rectangles.800* Thin ovals of girth 2 pixels are simple rectangles with801* potentially smaller lengths. Determine the correct length802* by calculating .5*.5 + scaledlen*scaledlen == 1.0 which803* means that scaledlen is the sqrt(0.75). Scaledlen is804* relative to the true length (w or h) and needs to be805* adjusted by half a pixel in different ways for odd or806* even lengths.807*/808#define SQRT_3_4 0.86602540378443864676809if (w > 2 && h > 1) {810int adjw = (int) ((SQRT_3_4 * w - ((w&1)-1)) * 0.5);811adjw = adjw * 2 + (w&1);812x += (w-adjw)/2;813w = adjw;814} else if (h > 2 && w > 1) {815int adjh = (int) ((SQRT_3_4 * h - ((h&1)-1)) * 0.5);816adjh = adjh * 2 + (h&1);817y += (h-adjh)/2;818h = adjh;819}820#undef SQRT_3_4821if (w > 0 && h > 0) {822XFillRectangle(awt_display, xsdo->drawable, (GC) xgc, x, y, w, h);823}824} else {825awt_drawArc(env, xsdo->drawable, (GC) xgc,826x, y, w, h, 0, 360, JNI_TRUE);827}828X11SD_DirectRenderNotify(env, xsdo);829#endif /* !HEADLESS */830}831832/*833* Class: sun_java2d_x11_X11Renderer834* Method: XFillArc835* Signature: (IJIIIIII)V836*/837JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillArc838(JNIEnv *env, jobject xr,839jlong pXSData, jlong xgc,840jint x, jint y, jint w, jint h,841jint angleStart, jint angleExtent)842{843#ifndef HEADLESS844X11SDOps *xsdo = (X11SDOps *) pXSData;845846if (xsdo == NULL) {847return;848}849850awt_drawArc(env, xsdo->drawable, (GC) xgc,851x, y, w, h, angleStart, angleExtent, JNI_TRUE);852X11SD_DirectRenderNotify(env, xsdo);853#endif /* !HEADLESS */854}855856/*857* Class: sun_java2d_x11_X11Renderer858* Method: XFillPoly859* Signature: (IJII[I[II)V860*/861JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillPoly862(JNIEnv *env, jobject xr,863jlong pXSData, jlong xgc,864jint transx, jint transy,865jintArray xcoordsArray, jintArray ycoordsArray, jint npoints)866{867#ifndef HEADLESS868XPoint pTmp[POLYTEMPSIZE], *points;869X11SDOps *xsdo = (X11SDOps *) pXSData;870871if (xsdo == NULL) {872return;873}874875if (JNU_IsNull(env, xcoordsArray) || JNU_IsNull(env, ycoordsArray)) {876JNU_ThrowNullPointerException(env, "coordinate array");877return;878}879if ((*env)->GetArrayLength(env, ycoordsArray) < npoints ||880(*env)->GetArrayLength(env, xcoordsArray) < npoints)881{882JNU_ThrowArrayIndexOutOfBoundsException(env, "coordinate array");883return;884}885886if (npoints < 3) {887return;888}889890points = transformPoints(env, xcoordsArray, ycoordsArray, transx, transy,891pTmp, (int *)&npoints, JNI_FALSE);892if (points != 0) {893if (npoints > 2) {894XFillPolygon(awt_display, xsdo->drawable, (GC) xgc,895points, npoints, Complex, CoordModeOrigin);896X11SD_DirectRenderNotify(env, xsdo);897}898if (points != pTmp) {899free(points);900}901}902#endif /* !HEADLESS */903}904905/*906* Class: sun_java2d_x11_X11Renderer907* Method: XFillSpans908* Signature: (IJLsun/java2d/pipe/SpanIterator;JII)V909*/910JNIEXPORT void JNICALL Java_sun_java2d_x11_X11Renderer_XFillSpans911(JNIEnv *env, jobject xr,912jlong pXSData, jlong xgc,913jobject si, jlong pIterator,914jint transx, jint transy)915{916#ifndef HEADLESS917SpanIteratorFuncs *pFuncs = (SpanIteratorFuncs *) jlong_to_ptr(pIterator);918void *srData;919jint x, y, w, h;920jint spanbox[4];921X11SDOps *xsdo = (X11SDOps *) pXSData;922923if (xsdo == NULL) {924return;925}926927if (JNU_IsNull(env, si)) {928JNU_ThrowNullPointerException(env, "span iterator");929return;930}931if (pFuncs == NULL) {932JNU_ThrowNullPointerException(env, "native iterator not supplied");933return;934}935936srData = (*pFuncs->open)(env, si);937while ((*pFuncs->nextSpan)(srData, spanbox)) {938x = spanbox[0] + transx;939y = spanbox[1] + transy;940w = spanbox[2] - spanbox[0];941h = spanbox[3] - spanbox[1];942XFillRectangle(awt_display, xsdo->drawable, (GC) xgc,943CLAMP_TO_SHORT(x), CLAMP_TO_SHORT(y),944CLAMP_TO_USHORT(w), CLAMP_TO_USHORT(h));945}946(*pFuncs->close)(env, srData);947X11SD_DirectRenderNotify(env, xsdo);948#endif /* !HEADLESS */949}950951/*952* Class: sun_java2d_x11_X11Renderer953* Method: devCopyArea954* Signature: (Lsun/java2d/SurfaceData;IIIIII)V955*/956JNIEXPORT void JNICALL957Java_sun_java2d_x11_X11Renderer_devCopyArea958(JNIEnv *env, jobject xr,959jlong xsd, jlong gc,960jint srcx, jint srcy,961jint dstx, jint dsty,962jint width, jint height)963{964#ifndef HEADLESS965X11SDOps *xsdo;966GC xgc;967968xsdo = (X11SDOps *)jlong_to_ptr(xsd);969if (xsdo == NULL) {970return;971}972973xgc = (GC)gc;974if (xgc == NULL) {975return;976}977978XCopyArea(awt_display, xsdo->drawable, xsdo->drawable, xgc,979srcx, srcy, width, height, dstx, dsty);980981X11SD_DirectRenderNotify(env, xsdo);982#endif /* !HEADLESS */983}984985986