1 /* 2 * Copyright (c) 2000, 2018, 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 26 package sun.java2d.x11; 27 28 import java.awt.Polygon; 29 import java.awt.Shape; 30 import java.awt.geom.AffineTransform; 31 import java.awt.geom.PathIterator; 32 import java.awt.geom.Path2D; 33 import java.awt.geom.IllegalPathStateException; 34 import sun.awt.SunToolkit; 35 import sun.java2d.SunGraphics2D; 36 import sun.java2d.SurfaceData; 37 import sun.java2d.loops.GraphicsPrimitive; 38 import sun.java2d.pipe.Region; 39 import sun.java2d.pipe.PixelDrawPipe; 40 import sun.java2d.pipe.PixelFillPipe; 41 import sun.java2d.pipe.ShapeDrawPipe; 42 import sun.java2d.pipe.SpanIterator; 43 import sun.java2d.pipe.ShapeSpanIterator; 44 import sun.java2d.pipe.LoopPipe; 45 46 public class X11Renderer implements 47 PixelDrawPipe, 48 PixelFillPipe, 49 ShapeDrawPipe 50 { getInstance()51 public static X11Renderer getInstance() { 52 return (GraphicsPrimitive.tracingEnabled() 53 ? new X11TracingRenderer() 54 : new X11Renderer()); 55 } 56 validate(SunGraphics2D sg2d)57 private long validate(SunGraphics2D sg2d) { 58 // NOTE: getCompClip() will revalidateAll() if the 59 // surfaceData is invalid. This should ensure that 60 // the clip and pixel that we are validating against 61 // are the most current. 62 // 63 // The assumption is that the pipeline after that 64 // revalidation will either be another X11 pipe 65 // (because the drawable format never changes on X11) 66 // or a null pipeline if the surface is disposed. 67 // 68 // Since we do not get the ops structure of the SurfaceData 69 // until the actual call down to the native level we will 70 // pick up the most recently validated copy. 71 // Note that if the surface is disposed, a NullSurfaceData 72 // (with null native data structure) will be set in 73 // sg2d, so we have to protect against it in native code. 74 75 X11SurfaceData x11sd = (X11SurfaceData)sg2d.surfaceData; 76 return x11sd.getRenderGC(sg2d.getCompClip(), 77 sg2d.compositeState, sg2d.composite, 78 sg2d.pixel); 79 } 80 XDrawLine(long pXSData, long xgc, int x1, int y1, int x2, int y2)81 native void XDrawLine(long pXSData, long xgc, 82 int x1, int y1, int x2, int y2); 83 drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2)84 public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) { 85 SunToolkit.awtLock(); 86 try { 87 long xgc = validate(sg2d); 88 int transx = sg2d.transX; 89 int transy = sg2d.transY; 90 XDrawLine(sg2d.surfaceData.getNativeOps(), xgc, 91 x1+transx, y1+transy, x2+transx, y2+transy); 92 } finally { 93 SunToolkit.awtUnlock(); 94 } 95 } 96 XDrawRect(long pXSData, long xgc, int x, int y, int w, int h)97 native void XDrawRect(long pXSData, long xgc, 98 int x, int y, int w, int h); 99 drawRect(SunGraphics2D sg2d, int x, int y, int width, int height)100 public void drawRect(SunGraphics2D sg2d, 101 int x, int y, int width, int height) 102 { 103 SunToolkit.awtLock(); 104 try { 105 long xgc = validate(sg2d); 106 XDrawRect(sg2d.surfaceData.getNativeOps(), xgc, 107 x+sg2d.transX, y+sg2d.transY, width, height); 108 } finally { 109 SunToolkit.awtUnlock(); 110 } 111 } 112 XDrawRoundRect(long pXSData, long xgc, int x, int y, int w, int h, int arcW, int arcH)113 native void XDrawRoundRect(long pXSData, long xgc, 114 int x, int y, int w, int h, 115 int arcW, int arcH); 116 drawRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight)117 public void drawRoundRect(SunGraphics2D sg2d, 118 int x, int y, int width, int height, 119 int arcWidth, int arcHeight) 120 { 121 SunToolkit.awtLock(); 122 try { 123 long xgc = validate(sg2d); 124 XDrawRoundRect(sg2d.surfaceData.getNativeOps(), xgc, 125 x+sg2d.transX, y+sg2d.transY, width, height, 126 arcWidth, arcHeight); 127 } finally { 128 SunToolkit.awtUnlock(); 129 } 130 } 131 XDrawOval(long pXSData, long xgc, int x, int y, int w, int h)132 native void XDrawOval(long pXSData, long xgc, 133 int x, int y, int w, int h); 134 drawOval(SunGraphics2D sg2d, int x, int y, int width, int height)135 public void drawOval(SunGraphics2D sg2d, 136 int x, int y, int width, int height) 137 { 138 SunToolkit.awtLock(); 139 try { 140 long xgc = validate(sg2d); 141 XDrawOval(sg2d.surfaceData.getNativeOps(), xgc, 142 x+sg2d.transX, y+sg2d.transY, width, height); 143 } finally { 144 SunToolkit.awtUnlock(); 145 } 146 } 147 XDrawArc(long pXSData, long xgc, int x, int y, int w, int h, int angleStart, int angleExtent)148 native void XDrawArc(long pXSData, long xgc, 149 int x, int y, int w, int h, 150 int angleStart, int angleExtent); 151 drawArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle)152 public void drawArc(SunGraphics2D sg2d, 153 int x, int y, int width, int height, 154 int startAngle, int arcAngle) 155 { 156 SunToolkit.awtLock(); 157 try { 158 long xgc = validate(sg2d); 159 XDrawArc(sg2d.surfaceData.getNativeOps(), xgc, 160 x+sg2d.transX, y+sg2d.transY, width, height, 161 startAngle, arcAngle); 162 } finally { 163 SunToolkit.awtUnlock(); 164 } 165 } 166 XDrawPoly(long pXSData, long xgc, int transx, int transy, int[] xpoints, int[] ypoints, int npoints, boolean isclosed)167 native void XDrawPoly(long pXSData, long xgc, 168 int transx, int transy, 169 int[] xpoints, int[] ypoints, 170 int npoints, boolean isclosed); 171 drawPolyline(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints)172 public void drawPolyline(SunGraphics2D sg2d, 173 int[] xpoints, int[] ypoints, 174 int npoints) 175 { 176 SunToolkit.awtLock(); 177 try { 178 long xgc = validate(sg2d); 179 XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc, 180 sg2d.transX, sg2d.transY, 181 xpoints, ypoints, npoints, false); 182 } finally { 183 SunToolkit.awtUnlock(); 184 } 185 } 186 drawPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints)187 public void drawPolygon(SunGraphics2D sg2d, 188 int[] xpoints, int[] ypoints, 189 int npoints) 190 { 191 SunToolkit.awtLock(); 192 try { 193 long xgc = validate(sg2d); 194 XDrawPoly(sg2d.surfaceData.getNativeOps(), xgc, 195 sg2d.transX, sg2d.transY, 196 xpoints, ypoints, npoints, true); 197 } finally { 198 SunToolkit.awtUnlock(); 199 } 200 } 201 XFillRect(long pXSData, long xgc, int x, int y, int w, int h)202 native void XFillRect(long pXSData, long xgc, 203 int x, int y, int w, int h); 204 fillRect(SunGraphics2D sg2d, int x, int y, int width, int height)205 public void fillRect(SunGraphics2D sg2d, 206 int x, int y, int width, int height) 207 { 208 SunToolkit.awtLock(); 209 try { 210 long xgc = validate(sg2d); 211 XFillRect(sg2d.surfaceData.getNativeOps(), xgc, 212 x+sg2d.transX, y+sg2d.transY, width, height); 213 } finally { 214 SunToolkit.awtUnlock(); 215 } 216 } 217 XFillRoundRect(long pXSData, long xgc, int x, int y, int w, int h, int arcW, int arcH)218 native void XFillRoundRect(long pXSData, long xgc, 219 int x, int y, int w, int h, 220 int arcW, int arcH); 221 fillRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight)222 public void fillRoundRect(SunGraphics2D sg2d, 223 int x, int y, int width, int height, 224 int arcWidth, int arcHeight) 225 { 226 SunToolkit.awtLock(); 227 try { 228 long xgc = validate(sg2d); 229 XFillRoundRect(sg2d.surfaceData.getNativeOps(), xgc, 230 x+sg2d.transX, y+sg2d.transY, width, height, 231 arcWidth, arcHeight); 232 } finally { 233 SunToolkit.awtUnlock(); 234 } 235 } 236 XFillOval(long pXSData, long xgc, int x, int y, int w, int h)237 native void XFillOval(long pXSData, long xgc, 238 int x, int y, int w, int h); 239 fillOval(SunGraphics2D sg2d, int x, int y, int width, int height)240 public void fillOval(SunGraphics2D sg2d, 241 int x, int y, int width, int height) 242 { 243 SunToolkit.awtLock(); 244 try { 245 long xgc = validate(sg2d); 246 XFillOval(sg2d.surfaceData.getNativeOps(), xgc, 247 x+sg2d.transX, y+sg2d.transY, width, height); 248 } finally { 249 SunToolkit.awtUnlock(); 250 } 251 } 252 XFillArc(long pXSData, long xgc, int x, int y, int w, int h, int angleStart, int angleExtent)253 native void XFillArc(long pXSData, long xgc, 254 int x, int y, int w, int h, 255 int angleStart, int angleExtent); 256 fillArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle)257 public void fillArc(SunGraphics2D sg2d, 258 int x, int y, int width, int height, 259 int startAngle, int arcAngle) 260 { 261 SunToolkit.awtLock(); 262 try { 263 long xgc = validate(sg2d); 264 XFillArc(sg2d.surfaceData.getNativeOps(), xgc, 265 x+sg2d.transX, y+sg2d.transY, width, height, 266 startAngle, arcAngle); 267 } finally { 268 SunToolkit.awtUnlock(); 269 } 270 } 271 XFillPoly(long pXSData, long xgc, int transx, int transy, int[] xpoints, int[] ypoints, int npoints)272 native void XFillPoly(long pXSData, long xgc, 273 int transx, int transy, 274 int[] xpoints, int[] ypoints, 275 int npoints); 276 fillPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints)277 public void fillPolygon(SunGraphics2D sg2d, 278 int[] xpoints, int[] ypoints, 279 int npoints) 280 { 281 SunToolkit.awtLock(); 282 try { 283 long xgc = validate(sg2d); 284 XFillPoly(sg2d.surfaceData.getNativeOps(), xgc, 285 sg2d.transX, sg2d.transY, xpoints, ypoints, npoints); 286 } finally { 287 SunToolkit.awtUnlock(); 288 } 289 } 290 XFillSpans(long pXSData, long xgc, SpanIterator si, long iterator, int transx, int transy)291 native void XFillSpans(long pXSData, long xgc, 292 SpanIterator si, long iterator, 293 int transx, int transy); 294 XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, int transX, int transY, Path2D.Float p2df, boolean isFill)295 native void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, 296 int transX, int transY, Path2D.Float p2df, 297 boolean isFill); 298 doPath(SunGraphics2D sg2d, Shape s, boolean isFill)299 private void doPath(SunGraphics2D sg2d, Shape s, boolean isFill) { 300 Path2D.Float p2df; 301 int transx, transy; 302 if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) { 303 if (s instanceof Path2D.Float) { 304 p2df = (Path2D.Float)s; 305 } else { 306 p2df = new Path2D.Float(s); 307 } 308 transx = sg2d.transX; 309 transy = sg2d.transY; 310 } else { 311 p2df = new Path2D.Float(s, sg2d.transform); 312 transx = 0; 313 transy = 0; 314 } 315 SunToolkit.awtLock(); 316 try { 317 long xgc = validate(sg2d); 318 XDoPath(sg2d, sg2d.surfaceData.getNativeOps(), xgc, 319 transx, transy, p2df, isFill); 320 } finally { 321 SunToolkit.awtUnlock(); 322 } 323 } 324 draw(SunGraphics2D sg2d, Shape s)325 public void draw(SunGraphics2D sg2d, Shape s) { 326 if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) { 327 // Delegate to drawPolygon() if possible... 328 if (s instanceof Polygon && 329 sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE) 330 { 331 Polygon p = (Polygon) s; 332 drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints); 333 return; 334 } 335 336 // Otherwise we will use drawPath() for 337 // high-quality thin paths. 338 doPath(sg2d, s, false); 339 } else if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) { 340 // REMIND: X11 can handle uniform scaled wide lines 341 // and dashed lines itself if we set the appropriate 342 // XGC attributes (TBD). 343 ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s); 344 try { 345 SunToolkit.awtLock(); 346 try { 347 long xgc = validate(sg2d); 348 XFillSpans(sg2d.surfaceData.getNativeOps(), xgc, 349 si, si.getNativeIterator(), 350 0, 0); 351 } finally { 352 SunToolkit.awtUnlock(); 353 } 354 } finally { 355 si.dispose(); 356 } 357 } else { 358 fill(sg2d, sg2d.stroke.createStrokedShape(s)); 359 } 360 } 361 fill(SunGraphics2D sg2d, Shape s)362 public void fill(SunGraphics2D sg2d, Shape s) { 363 if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) { 364 // Delegate to fillPolygon() if possible... 365 if (s instanceof Polygon && 366 sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE) 367 { 368 Polygon p = (Polygon) s; 369 fillPolygon(sg2d, p.xpoints, p.ypoints, p.npoints); 370 return; 371 } 372 373 // Otherwise we will use fillPath() for 374 // high-quality fills. 375 doPath(sg2d, s, true); 376 return; 377 } 378 379 AffineTransform at; 380 int transx, transy; 381 if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 382 // Transform (translation) will be done by XFillSpans 383 at = null; 384 transx = sg2d.transX; 385 transy = sg2d.transY; 386 } else { 387 // Transform will be done by the PathIterator 388 at = sg2d.transform; 389 transx = transy = 0; 390 } 391 392 ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d); 393 try { 394 // Subtract transx/y from the SSI clip to match the 395 // (potentially untranslated) geometry fed to it 396 Region clip = sg2d.getCompClip(); 397 ssi.setOutputAreaXYXY(clip.getLoX() - transx, 398 clip.getLoY() - transy, 399 clip.getHiX() - transx, 400 clip.getHiY() - transy); 401 ssi.appendPath(s.getPathIterator(at)); 402 SunToolkit.awtLock(); 403 try { 404 long xgc = validate(sg2d); 405 XFillSpans(sg2d.surfaceData.getNativeOps(), xgc, 406 ssi, ssi.getNativeIterator(), 407 transx, transy); 408 } finally { 409 SunToolkit.awtUnlock(); 410 } 411 } finally { 412 ssi.dispose(); 413 } 414 } 415 devCopyArea(long sdOps, long xgc, int srcx, int srcy, int dstx, int dsty, int w, int h)416 native void devCopyArea(long sdOps, long xgc, 417 int srcx, int srcy, 418 int dstx, int dsty, 419 int w, int h); 420 421 public static class X11TracingRenderer extends X11Renderer { XDrawLine(long pXSData, long xgc, int x1, int y1, int x2, int y2)422 void XDrawLine(long pXSData, long xgc, 423 int x1, int y1, int x2, int y2) 424 { 425 GraphicsPrimitive.tracePrimitive("X11DrawLine"); 426 super.XDrawLine(pXSData, xgc, x1, y1, x2, y2); 427 } XDrawRect(long pXSData, long xgc, int x, int y, int w, int h)428 void XDrawRect(long pXSData, long xgc, 429 int x, int y, int w, int h) 430 { 431 GraphicsPrimitive.tracePrimitive("X11DrawRect"); 432 super.XDrawRect(pXSData, xgc, x, y, w, h); 433 } XDrawRoundRect(long pXSData, long xgc, int x, int y, int w, int h, int arcW, int arcH)434 void XDrawRoundRect(long pXSData, long xgc, 435 int x, int y, int w, int h, 436 int arcW, int arcH) 437 { 438 GraphicsPrimitive.tracePrimitive("X11DrawRoundRect"); 439 super.XDrawRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH); 440 } XDrawOval(long pXSData, long xgc, int x, int y, int w, int h)441 void XDrawOval(long pXSData, long xgc, 442 int x, int y, int w, int h) 443 { 444 GraphicsPrimitive.tracePrimitive("X11DrawOval"); 445 super.XDrawOval(pXSData, xgc, x, y, w, h); 446 } XDrawArc(long pXSData, long xgc, int x, int y, int w, int h, int angleStart, int angleExtent)447 void XDrawArc(long pXSData, long xgc, 448 int x, int y, int w, int h, 449 int angleStart, int angleExtent) 450 { 451 GraphicsPrimitive.tracePrimitive("X11DrawArc"); 452 super.XDrawArc(pXSData, xgc, 453 x, y, w, h, angleStart, angleExtent); 454 } XDrawPoly(long pXSData, long xgc, int transx, int transy, int[] xpoints, int[] ypoints, int npoints, boolean isclosed)455 void XDrawPoly(long pXSData, long xgc, 456 int transx, int transy, 457 int[] xpoints, int[] ypoints, 458 int npoints, boolean isclosed) 459 { 460 GraphicsPrimitive.tracePrimitive("X11DrawPoly"); 461 super.XDrawPoly(pXSData, xgc, transx, transy, 462 xpoints, ypoints, npoints, isclosed); 463 } XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, int transX, int transY, Path2D.Float p2df, boolean isFill)464 void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, 465 int transX, int transY, Path2D.Float p2df, 466 boolean isFill) 467 { 468 GraphicsPrimitive.tracePrimitive(isFill ? 469 "X11FillPath" : 470 "X11DrawPath"); 471 super.XDoPath(sg2d, pXSData, xgc, transX, transY, p2df, isFill); 472 } XFillRect(long pXSData, long xgc, int x, int y, int w, int h)473 void XFillRect(long pXSData, long xgc, 474 int x, int y, int w, int h) 475 { 476 GraphicsPrimitive.tracePrimitive("X11FillRect"); 477 super.XFillRect(pXSData, xgc, x, y, w, h); 478 } XFillRoundRect(long pXSData, long xgc, int x, int y, int w, int h, int arcW, int arcH)479 void XFillRoundRect(long pXSData, long xgc, 480 int x, int y, int w, int h, 481 int arcW, int arcH) 482 { 483 GraphicsPrimitive.tracePrimitive("X11FillRoundRect"); 484 super.XFillRoundRect(pXSData, xgc, x, y, w, h, arcW, arcH); 485 } XFillOval(long pXSData, long xgc, int x, int y, int w, int h)486 void XFillOval(long pXSData, long xgc, 487 int x, int y, int w, int h) 488 { 489 GraphicsPrimitive.tracePrimitive("X11FillOval"); 490 super.XFillOval(pXSData, xgc, x, y, w, h); 491 } XFillArc(long pXSData, long xgc, int x, int y, int w, int h, int angleStart, int angleExtent)492 void XFillArc(long pXSData, long xgc, 493 int x, int y, int w, int h, 494 int angleStart, int angleExtent) 495 { 496 GraphicsPrimitive.tracePrimitive("X11FillArc"); 497 super.XFillArc(pXSData, xgc, 498 x, y, w, h, angleStart, angleExtent); 499 } XFillPoly(long pXSData, long xgc, int transx, int transy, int[] xpoints, int[] ypoints, int npoints)500 void XFillPoly(long pXSData, long xgc, 501 int transx, int transy, 502 int[] xpoints, int[] ypoints, 503 int npoints) 504 { 505 GraphicsPrimitive.tracePrimitive("X11FillPoly"); 506 super.XFillPoly(pXSData, xgc, 507 transx, transy, xpoints, ypoints, npoints); 508 } XFillSpans(long pXSData, long xgc, SpanIterator si, long iterator, int transx, int transy)509 void XFillSpans(long pXSData, long xgc, 510 SpanIterator si, long iterator, int transx, int transy) 511 { 512 GraphicsPrimitive.tracePrimitive("X11FillSpans"); 513 super.XFillSpans(pXSData, xgc, 514 si, iterator, transx, transy); 515 } devCopyArea(long sdOps, long xgc, int srcx, int srcy, int dstx, int dsty, int w, int h)516 void devCopyArea(long sdOps, long xgc, 517 int srcx, int srcy, 518 int dstx, int dsty, 519 int w, int h) 520 { 521 GraphicsPrimitive.tracePrimitive("X11CopyArea"); 522 super.devCopyArea(sdOps, xgc, srcx, srcy, dstx, dsty, w, h); 523 } 524 } 525 } 526