PageRenderTime 80ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/solaris/native/sun/java2d/x11/X11Renderer.c

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