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 { 51 public static X11Renderer getInstance() { 52 return (GraphicsPrimitive.tracingEnabled() 53 ? new X11TracingRenderer() 54 : new X11Renderer()); 55 } 56 57 private final 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 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 291 native void XFillSpans(long pXSData, long xgc, 292 SpanIterator si, long iterator, 293 int transx, int transy); 294 295 native void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, 296 int transX, int transY, Path2D.Float p2df, 297 boolean isFill); 298 299 private void doPath(SunGraphics2D sg2d, Shape s, boolean isFill) { 300 Path2D.Float p2df; 301 int transx, transy; 302 if (sg2d.transformState <= sg2d.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 325 public void draw(SunGraphics2D sg2d, Shape s) { 326 if (sg2d.strokeState == sg2d.STROKE_THIN) { 327 // Delegate to drawPolygon() if possible... 328 if (s instanceof Polygon && 329 sg2d.transformState < sg2d.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 < sg2d.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 362 public void fill(SunGraphics2D sg2d, Shape s) { 363 if (sg2d.strokeState == sg2d.STROKE_THIN) { 364 // Delegate to fillPolygon() if possible... 365 if (s instanceof Polygon && 366 sg2d.transformState < sg2d.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 < sg2d.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)); | 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.Path2D; 32 33 import sun.awt.SunToolkit; 34 import sun.java2d.SunGraphics2D; 35 import sun.java2d.loops.GraphicsPrimitive; 36 import sun.java2d.pipe.LoopPipe; 37 import sun.java2d.pipe.PixelDrawPipe; 38 import sun.java2d.pipe.PixelFillPipe; 39 import sun.java2d.pipe.Region; 40 import sun.java2d.pipe.ShapeDrawPipe; 41 import sun.java2d.pipe.ShapeSpanIterator; 42 import sun.java2d.pipe.SpanIterator; 43 44 public class X11Renderer implements 45 PixelDrawPipe, 46 PixelFillPipe, 47 ShapeDrawPipe 48 { 49 public static X11Renderer getInstance() { 50 return (GraphicsPrimitive.tracingEnabled() 51 ? new X11TracingRenderer() 52 : new X11Renderer()); 53 } 54 55 private final long validate(SunGraphics2D sg2d) { 56 // NOTE: getCompClip() will revalidateAll() if the 57 // surfaceData is invalid. This should ensure that 58 // the clip and pixel that we are validating against 59 // are the most current. 60 // 61 // The assumption is that the pipeline after that 62 // revalidation will either be another X11 pipe 280 try { 281 long xgc = validate(sg2d); 282 XFillPoly(sg2d.surfaceData.getNativeOps(), xgc, 283 sg2d.transX, sg2d.transY, xpoints, ypoints, npoints); 284 } finally { 285 SunToolkit.awtUnlock(); 286 } 287 } 288 289 native void XFillSpans(long pXSData, long xgc, 290 SpanIterator si, long iterator, 291 int transx, int transy); 292 293 native void XDoPath(SunGraphics2D sg2d, long pXSData, long xgc, 294 int transX, int transY, Path2D.Float p2df, 295 boolean isFill); 296 297 private void doPath(SunGraphics2D sg2d, Shape s, boolean isFill) { 298 Path2D.Float p2df; 299 int transx, transy; 300 if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) { 301 if (s instanceof Path2D.Float) { 302 p2df = (Path2D.Float)s; 303 } else { 304 p2df = new Path2D.Float(s); 305 } 306 transx = sg2d.transX; 307 transy = sg2d.transY; 308 } else { 309 p2df = new Path2D.Float(s, sg2d.transform); 310 transx = 0; 311 transy = 0; 312 } 313 SunToolkit.awtLock(); 314 try { 315 long xgc = validate(sg2d); 316 XDoPath(sg2d, sg2d.surfaceData.getNativeOps(), xgc, 317 transx, transy, p2df, isFill); 318 } finally { 319 SunToolkit.awtUnlock(); 320 } 321 } 322 323 public void draw(SunGraphics2D sg2d, Shape s) { 324 if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) { 325 // Delegate to drawPolygon() if possible... 326 if (s instanceof Polygon && 327 sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE) 328 { 329 Polygon p = (Polygon) s; 330 drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints); 331 return; 332 } 333 334 // Otherwise we will use drawPath() for 335 // high-quality thin paths. 336 doPath(sg2d, s, false); 337 } else if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) { 338 // REMIND: X11 can handle uniform scaled wide lines 339 // and dashed lines itself if we set the appropriate 340 // XGC attributes (TBD). 341 ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s); 342 try { 343 SunToolkit.awtLock(); 344 try { 345 long xgc = validate(sg2d); 346 XFillSpans(sg2d.surfaceData.getNativeOps(), xgc, 347 si, si.getNativeIterator(), 348 0, 0); 349 } finally { 350 SunToolkit.awtUnlock(); 351 } 352 } finally { 353 si.dispose(); 354 } 355 } else { 356 fill(sg2d, sg2d.stroke.createStrokedShape(s)); 357 } 358 } 359 360 public void fill(SunGraphics2D sg2d, Shape s) { 361 if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) { 362 // Delegate to fillPolygon() if possible... 363 if (s instanceof Polygon && 364 sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE) 365 { 366 Polygon p = (Polygon) s; 367 fillPolygon(sg2d, p.xpoints, p.ypoints, p.npoints); 368 return; 369 } 370 371 // Otherwise we will use fillPath() for 372 // high-quality fills. 373 doPath(sg2d, s, true); 374 return; 375 } 376 377 AffineTransform at; 378 int transx, transy; 379 if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 380 // Transform (translation) will be done by XFillSpans 381 at = null; 382 transx = sg2d.transX; 383 transy = sg2d.transY; 384 } else { 385 // Transform will be done by the PathIterator 386 at = sg2d.transform; 387 transx = transy = 0; 388 } 389 390 ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d); 391 try { 392 // Subtract transx/y from the SSI clip to match the 393 // (potentially untranslated) geometry fed to it 394 Region clip = sg2d.getCompClip(); 395 ssi.setOutputAreaXYXY(clip.getLoX() - transx, 396 clip.getLoY() - transy, 397 clip.getHiX() - transx, 398 clip.getHiY() - transy); 399 ssi.appendPath(s.getPathIterator(at)); |