1 /* 2 * Copyright (c) 2010, 2013, 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.xr; 27 28 import java.awt.*; 29 import java.awt.geom.*; 30 import java.awt.image.*; 31 import sun.awt.*; 32 import sun.java2d.InvalidPipeException; 33 import sun.java2d.SunGraphics2D; 34 import sun.java2d.SurfaceData; 35 import sun.java2d.SurfaceDataProxy; 36 import sun.java2d.jules.*; 37 import sun.java2d.loops.*; 38 import sun.java2d.pipe.*; 39 import sun.java2d.x11.*; 40 import sun.font.FontManagerNativeLibrary; 41 42 public abstract class XRSurfaceData extends XSurfaceData { 43 X11ComponentPeer peer; 44 XRGraphicsConfig graphicsConfig; 45 XRBackend renderQueue; 46 47 private RenderLoops solidloops; 48 49 protected int depth; 50 51 private static native void initIDs(); 52 53 protected native void XRInitSurface(int depth, int width, int height, 54 long drawable, int pictFormat); 55 56 native void initXRPicture(long xsdo, int pictForm); 57 58 native void freeXSDOPicture(long xsdo); 59 60 public static final String DESC_BYTE_A8_X11 = "Byte A8 Pixmap"; 61 public static final String DESC_INT_RGB_X11 = "Integer RGB Pixmap"; 62 public static final String DESC_INT_ARGB_X11 = "Integer ARGB-Pre Pixmap"; 63 64 public static final SurfaceType 65 ByteA8X11 = SurfaceType.ByteGray.deriveSubType(DESC_BYTE_A8_X11); 66 public static final SurfaceType 67 IntRgbX11 = SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_X11); 68 public static final SurfaceType 69 IntArgbPreX11 = SurfaceType.IntArgbPre.deriveSubType(DESC_INT_ARGB_X11); 70 71 public Raster getRaster(int x, int y, int w, int h) { 72 throw new InternalError("not implemented yet"); 73 } 74 75 protected XRRenderer xrpipe; 76 protected PixelToShapeConverter xrtxpipe; 77 protected TextPipe xrtextpipe; 78 protected XRDrawImage xrDrawImage; 79 80 protected ShapeDrawPipe aaShapePipe; 81 protected PixelToShapeConverter aaPixelToShapeConv; 82 83 public static void initXRSurfaceData() { 84 if (!isX11SurfaceDataInitialized()) { 85 FontManagerNativeLibrary.load(); 86 initIDs(); 87 XRPMBlitLoops.register(); 88 XRMaskFill.register(); 89 XRMaskBlit.register(); 90 91 setX11SurfaceDataInitialized(); 92 } 93 } 94 95 /** 96 * Synchronized accessor method for isDrawableValid. 97 */ 98 protected boolean isXRDrawableValid() { 99 try { 100 SunToolkit.awtLock(); 101 return isDrawableValid(); 102 } finally { 103 SunToolkit.awtUnlock(); 104 } 105 } 106 107 @Override 108 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 109 return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig); 110 } 111 112 @Override 113 public void validatePipe(SunGraphics2D sg2d) { 114 TextPipe textpipe; 115 boolean validated = false; 116 117 /* 118 * The textpipe for now can't handle TexturePaint when extra-alpha is 119 * specified nore XOR mode 120 */ 121 if ((textpipe = getTextPipe(sg2d)) == null) 122 { 123 super.validatePipe(sg2d); 124 textpipe = sg2d.textpipe; 125 validated = true; 126 } 127 128 PixelToShapeConverter txPipe = null; 129 XRRenderer nonTxPipe = null; 130 131 /* 132 * TODO: Can we rely on the GC for ARGB32 surfaces? 133 */ 134 if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) { 135 if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) { 136 if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) { 137 txPipe = xrtxpipe; 138 nonTxPipe = xrpipe; 139 } 140 } else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) { 141 if (XRPaints.isValid(sg2d)) { 142 txPipe = xrtxpipe; 143 nonTxPipe = xrpipe; 144 } 145 // custom paints handled by super.validatePipe() below 146 } 147 } 148 149 if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON && 150 JulesPathBuf.isCairoAvailable()) 151 { 152 sg2d.shapepipe = aaShapePipe; 153 sg2d.drawpipe = aaPixelToShapeConv; 154 sg2d.fillpipe = aaPixelToShapeConv; 155 } else { 156 if (txPipe != null) { 157 if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 158 sg2d.drawpipe = txPipe; 159 sg2d.fillpipe = txPipe; 160 } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) { 161 sg2d.drawpipe = txPipe; 162 sg2d.fillpipe = nonTxPipe; 163 } else { 164 sg2d.drawpipe = nonTxPipe; 165 sg2d.fillpipe = nonTxPipe; 166 } 167 sg2d.shapepipe = nonTxPipe; 168 } else { 169 if (!validated) { 170 super.validatePipe(sg2d); 171 } 172 } 173 } 174 175 // install the text pipe based on our earlier decision 176 sg2d.textpipe = textpipe; 177 178 // always override the image pipe with the specialized XRender pipe 179 sg2d.imagepipe = xrDrawImage; 180 } 181 182 protected TextPipe getTextPipe(SunGraphics2D sg2d) { 183 boolean supportedPaint = sg2d.compositeState <= SunGraphics2D.COMP_ALPHA 184 && (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR || sg2d.composite == null); 185 186 boolean supportedCompOp = false; 187 if (sg2d.composite instanceof AlphaComposite) { 188 int compRule = ((AlphaComposite) sg2d.composite).getRule(); 189 supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(compRule)) 190 || (compRule == AlphaComposite.SRC 191 && sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR); 192 } 193 194 return (supportedPaint && supportedCompOp) ? xrtextpipe : null; 195 } 196 197 protected MaskFill getMaskFill(SunGraphics2D sg2d) { 198 AlphaComposite aComp = null; 199 if(sg2d.composite != null 200 && sg2d.composite instanceof AlphaComposite) { 201 aComp = (AlphaComposite) sg2d.composite; 202 } 203 204 boolean supportedPaint = sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR 205 || XRPaints.isValid(sg2d); 206 207 boolean supportedCompOp = false; 208 if(aComp != null) { 209 int rule = aComp.getRule(); 210 supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(rule)); 211 } 212 213 return (supportedPaint && supportedCompOp) ? super.getMaskFill(sg2d) : null; 214 } 215 216 public RenderLoops getRenderLoops(SunGraphics2D sg2d) { 217 if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR && 218 sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) 219 { 220 return solidloops; 221 } 222 223 return super.getRenderLoops(sg2d); 224 } 225 226 public GraphicsConfiguration getDeviceConfiguration() { 227 return graphicsConfig; 228 } 229 230 /** 231 * Method for instantiating a Window SurfaceData 232 */ 233 public static XRWindowSurfaceData createData(X11ComponentPeer peer) { 234 XRGraphicsConfig gc = getGC(peer); 235 return new XRWindowSurfaceData(peer, gc, gc.getSurfaceType()); 236 } 237 238 /** 239 * Method for instantiating a Pixmap SurfaceData (offscreen). 240 * If the surface * is opaque a 24-bit/RGB surface is chosen, 241 * otherwise a 32-bit ARGB surface. 242 */ 243 public static XRPixmapSurfaceData createData(XRGraphicsConfig gc, 244 int width, int height, 245 ColorModel cm, Image image, 246 long drawable, 247 int transparency, 248 boolean isTexture) { 249 int depth; 250 // If we have a 32 bit color model for the window it needs 251 // alpha to support translucency of the window so we need 252 // to upgrade what was requested for the surface. 253 if (gc.getColorModel().getPixelSize() == 32) { 254 depth = 32; 255 transparency = Transparency.TRANSLUCENT; 256 } else { 257 depth = transparency > Transparency.OPAQUE ? 32 : 24; 258 } 259 260 if (depth == 24) { 261 cm = new DirectColorModel(depth, 262 0x00FF0000, 0x0000FF00, 0x000000FF); 263 } else { 264 cm = new DirectColorModel(depth, 0x00FF0000, 0x0000FF00, 265 0x000000FF, 0xFF000000); 266 } 267 268 return new XRPixmapSurfaceData 269 (gc, width, height, image, getSurfaceType(gc, transparency), 270 cm, drawable, transparency, 271 XRUtils.getPictureFormatForTransparency(transparency), depth, isTexture); 272 } 273 274 protected XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc, 275 SurfaceType sType, ColorModel cm, int depth, int transparency) 276 { 277 super(sType, cm); 278 this.peer = peer; 279 this.graphicsConfig = gc; 280 this.solidloops = graphicsConfig.getSolidLoops(sType); 281 this.depth = depth; 282 initOps(peer, graphicsConfig, depth); 283 284 setBlitProxyKey(gc.getProxyKey()); 285 } 286 287 protected XRSurfaceData(XRBackend renderQueue) { 288 super(XRSurfaceData.IntRgbX11, 289 new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF)); 290 this.renderQueue = renderQueue; 291 } 292 293 /** 294 * Inits the XRender-data-structures which belong to the XRSurfaceData. 295 * 296 * @param pictureFormat 297 */ 298 public void initXRender(int pictureFormat) { 299 try { 300 SunToolkit.awtLock(); 301 initXRPicture(getNativeOps(), pictureFormat); 302 renderQueue = XRCompositeManager.getInstance(this).getBackend(); 303 maskBuffer = XRCompositeManager.getInstance(this); 304 } catch (Throwable ex) { 305 ex.printStackTrace(); 306 } finally { 307 SunToolkit.awtUnlock(); 308 } 309 } 310 311 public static XRGraphicsConfig getGC(X11ComponentPeer peer) { 312 if (peer != null) { 313 return (XRGraphicsConfig) peer.getGraphicsConfiguration(); 314 } else { 315 GraphicsEnvironment env = 316 GraphicsEnvironment.getLocalGraphicsEnvironment(); 317 GraphicsDevice gd = env.getDefaultScreenDevice(); 318 return (XRGraphicsConfig) gd.getDefaultConfiguration(); 319 } 320 } 321 322 /** 323 * Returns a boolean indicating whether or not a copyArea from the given 324 * rectangle source coordinates might be incomplete and result in X11 325 * GraphicsExposure events being generated from XCopyArea. This method 326 * allows the SurfaceData copyArea method to determine if it needs to set 327 * the GraphicsExposures attribute of the X11 GC to True or False to receive 328 * or avoid the events. 329 * 330 * @return true if there is any chance that an XCopyArea from the given 331 * source coordinates could produce any X11 Exposure events. 332 */ 333 public abstract boolean canSourceSendExposures(int x, int y, int w, int h); 334 335 /** 336 * CopyArea is implemented using the "old" X11 GC, therefor clip and 337 * needExposures have to be validated against that GC. Pictures and GCs 338 * don't share state. 339 */ 340 public void validateCopyAreaGC(Region gcClip, boolean needExposures) { 341 if (validatedGCClip != gcClip) { 342 if (gcClip != null) 343 renderQueue.setGCClipRectangles(xgc, gcClip); 344 validatedGCClip = gcClip; 345 } 346 347 if (validatedExposures != needExposures) { 348 validatedExposures = needExposures; 349 renderQueue.setGCExposures(xgc, needExposures); 350 } 351 352 if (validatedXorComp != null) { 353 renderQueue.setGCMode(xgc, true); 354 renderQueue.setGCForeground(xgc, validatedGCForegroundPixel); 355 validatedXorComp = null; 356 } 357 } 358 359 public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, 360 int dx, int dy) { 361 if (xrpipe == null) { 362 if (!isXRDrawableValid()) { 363 return true; 364 } 365 makePipes(); 366 } 367 CompositeType comptype = sg2d.imageComp; 368 if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE && 369 (CompositeType.SrcOverNoEa.equals(comptype) || 370 CompositeType.SrcNoEa.equals(comptype))) 371 { 372 x += sg2d.transX; 373 y += sg2d.transY; 374 try { 375 SunToolkit.awtLock(); 376 boolean needExposures = canSourceSendExposures(x, y, w, h); 377 validateCopyAreaGC(sg2d.getCompClip(), needExposures); 378 renderQueue.copyArea(xid, xid, xgc, x, y, w, h, x + dx, y + dy); 379 } finally { 380 SunToolkit.awtUnlock(); 381 } 382 return true; 383 } 384 return false; 385 } 386 387 /** 388 * Returns the XRender SurfaceType which is able to fullfill the specified 389 * transparency requirement. 390 */ 391 public static SurfaceType getSurfaceType(XRGraphicsConfig gc, 392 int transparency) { 393 SurfaceType sType = null; 394 395 switch (transparency) { 396 case Transparency.OPAQUE: 397 sType = XRSurfaceData.IntRgbX11; 398 break; 399 400 case Transparency.BITMASK: 401 case Transparency.TRANSLUCENT: 402 sType = XRSurfaceData.IntArgbPreX11; 403 break; 404 } 405 406 return sType; 407 } 408 409 public void invalidate() { 410 if (isValid()) { 411 setInvalid(); 412 super.invalidate(); 413 } 414 } 415 416 private long xgc; // GC is still used for copyArea 417 private int validatedGCForegroundPixel = 0; 418 private XORComposite validatedXorComp; 419 private int xid; 420 public int picture; 421 public XRCompositeManager maskBuffer; 422 423 private Region validatedClip; 424 private Region validatedGCClip; 425 private boolean validatedExposures = true; 426 427 boolean transformInUse = false; 428 AffineTransform validatedSourceTransform = new AffineTransform(); 429 AffineTransform staticSrcTx = null; 430 int validatedRepeat = XRUtils.RepeatNone; 431 int validatedFilter = XRUtils.FAST; 432 433 /** 434 * Validates an XRSurfaceData when used as source. Note that the clip is 435 * applied when used as source as well as destination. 436 */ 437 void validateAsSource(AffineTransform sxForm, int repeat, int filter) { 438 439 if (validatedClip != null) { 440 validatedClip = null; 441 renderQueue.setClipRectangles(picture, null); 442 } 443 444 if (validatedRepeat != repeat && repeat != -1) { 445 validatedRepeat = repeat; 446 renderQueue.setPictureRepeat(picture, repeat); 447 } 448 449 if (sxForm == null) { 450 if (transformInUse) { 451 validatedSourceTransform.setToIdentity(); 452 renderQueue.setPictureTransform(picture, 453 validatedSourceTransform); 454 transformInUse = false; 455 } 456 } else if (!transformInUse || 457 (transformInUse && !sxForm.equals(validatedSourceTransform))) { 458 459 validatedSourceTransform.setTransform(sxForm.getScaleX(), 460 sxForm.getShearY(), 461 sxForm.getShearX(), 462 sxForm.getScaleY(), 463 sxForm.getTranslateX(), 464 sxForm.getTranslateY()); 465 466 AffineTransform srcTransform = validatedSourceTransform; 467 if(staticSrcTx != null) { 468 // Apply static transform set when used as texture or gradient. 469 // Create a copy to not modify validatedSourceTransform as 470 // this would confuse the validation logic. 471 srcTransform = new AffineTransform(validatedSourceTransform); 472 srcTransform.preConcatenate(staticSrcTx); 473 } 474 475 renderQueue.setPictureTransform(picture, srcTransform); 476 transformInUse = true; 477 } 478 479 if (filter != validatedFilter && filter != -1) { 480 renderQueue.setFilter(picture, filter); 481 validatedFilter = filter; 482 } 483 } 484 485 /** 486 * Validates the Surface when used as destination. 487 */ 488 public void validateAsDestination(SunGraphics2D sg2d, Region clip) { 489 if (!isValid()) { 490 throw new InvalidPipeException("bounds changed"); 491 } 492 493 boolean updateGCClip = false; 494 if (clip != validatedClip) { 495 renderQueue.setClipRectangles(picture, clip); 496 validatedClip = clip; 497 updateGCClip = true; 498 } 499 500 if (sg2d != null && sg2d.compositeState == SunGraphics2D.COMP_XOR) { 501 if (validatedXorComp != sg2d.getComposite()) { 502 validatedXorComp = (XORComposite) sg2d.getComposite(); 503 renderQueue.setGCMode(xgc, false); 504 } 505 506 // validate pixel 507 int pixel = sg2d.pixel; 508 if (validatedGCForegroundPixel != pixel) { 509 int xorpixelmod = validatedXorComp.getXorPixel(); 510 renderQueue.setGCForeground(xgc, pixel ^ xorpixelmod); 511 validatedGCForegroundPixel = pixel; 512 } 513 514 if (updateGCClip) { 515 renderQueue.setGCClipRectangles(xgc, clip); 516 } 517 } 518 } 519 520 public synchronized void makePipes() { /* 521 * TODO: Why is this synchronized, 522 * but access not? 523 */ 524 if (xrpipe == null) { 525 try { 526 SunToolkit.awtLock(); 527 xgc = XCreateGC(getNativeOps()); 528 529 xrpipe = new XRRenderer(maskBuffer.getMaskBuffer()); 530 xrtxpipe = new PixelToShapeConverter(xrpipe); 531 xrtextpipe = maskBuffer.getTextRenderer(); 532 xrDrawImage = new XRDrawImage(); 533 534 if (JulesPathBuf.isCairoAvailable()) { 535 aaShapePipe = 536 new JulesShapePipe(XRCompositeManager.getInstance(this)); 537 aaPixelToShapeConv = new PixelToShapeConverter(aaShapePipe); 538 } 539 } finally { 540 SunToolkit.awtUnlock(); 541 } 542 } 543 } 544 545 public static class XRWindowSurfaceData extends XRSurfaceData { 546 547 protected final int scale; 548 549 public XRWindowSurfaceData(X11ComponentPeer peer, 550 XRGraphicsConfig gc, SurfaceType sType) { 551 super(peer, gc, sType, peer.getColorModel(), 552 peer.getColorModel().getPixelSize(), Transparency.OPAQUE); 553 554 this.scale = gc.getScale(); 555 556 if (isXRDrawableValid()) { 557 // If we have a 32 bit color model for the window it needs 558 // alpha to support translucency of the window so we need 559 // to get the ARGB32 XRender picture format else for 560 // 24 bit colormodel we need RGB24 or OPAQUE pictureformat. 561 if (peer.getColorModel().getPixelSize() == 32) { 562 initXRender(XRUtils. 563 getPictureFormatForTransparency(Transparency.TRANSLUCENT)); 564 } 565 else { 566 initXRender(XRUtils. 567 getPictureFormatForTransparency(Transparency.OPAQUE)); 568 } 569 makePipes(); 570 } 571 } 572 573 public SurfaceData getReplacement() { 574 return peer.getSurfaceData(); 575 } 576 577 public Rectangle getBounds() { 578 Rectangle r = peer.getBounds(); 579 r.x = r.y = 0; 580 r.width *= scale; 581 r.height *= scale; 582 return r; 583 } 584 585 @Override 586 public boolean canSourceSendExposures(int x, int y, int w, int h) { 587 return true; 588 } 589 590 /** 591 * Returns destination Component associated with this SurfaceData. 592 */ 593 public Object getDestination() { 594 return peer.getTarget(); 595 } 596 597 public void invalidate() { 598 try { 599 SunToolkit.awtLock(); 600 freeXSDOPicture(getNativeOps()); 601 }finally { 602 SunToolkit.awtUnlock(); 603 } 604 605 super.invalidate(); 606 } 607 608 @Override 609 public double getDefaultScaleX() { 610 return scale; 611 } 612 613 @Override 614 public double getDefaultScaleY() { 615 return scale; 616 } 617 } 618 619 public static class XRInternalSurfaceData extends XRSurfaceData { 620 public XRInternalSurfaceData(XRBackend renderQueue, int pictXid) { 621 super(renderQueue); 622 this.picture = pictXid; 623 this.transformInUse = false; 624 } 625 626 public boolean canSourceSendExposures(int x, int y, int w, int h) { 627 return false; 628 } 629 630 public Rectangle getBounds() { 631 return null; 632 } 633 634 public Object getDestination() { 635 return null; 636 } 637 638 public SurfaceData getReplacement() { 639 return null; 640 } 641 } 642 643 public static class XRPixmapSurfaceData extends XRSurfaceData { 644 Image offscreenImage; 645 int width; 646 int height; 647 int transparency; 648 private final int scale; 649 650 public XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height, 651 Image image, SurfaceType sType, 652 ColorModel cm, long drawable, 653 int transparency, int pictFormat, 654 int depth, boolean isTexture) { 655 super(null, gc, sType, cm, depth, transparency); 656 this.scale = isTexture ? 1 : gc.getDevice().getScaleFactor(); 657 this.width = width * scale; 658 this.height = height * scale; 659 offscreenImage = image; 660 this.transparency = transparency; 661 initSurface(depth, this.width, this.height, drawable, pictFormat); 662 663 initXRender(pictFormat); 664 makePipes(); 665 } 666 667 public void initSurface(int depth, int width, int height, 668 long drawable, int pictFormat) { 669 try { 670 SunToolkit.awtLock(); 671 XRInitSurface(depth, width, height, drawable, pictFormat); 672 } finally { 673 SunToolkit.awtUnlock(); 674 } 675 } 676 677 public SurfaceData getReplacement() { 678 return restoreContents(offscreenImage); 679 } 680 681 /** 682 * Need this since the surface data is created with the color model of 683 * the target GC, which is always opaque. But in SunGraphics2D.blitSD we 684 * choose loops based on the transparency on the source SD, so it could 685 * choose wrong loop (blit instead of blitbg, for example). 686 */ 687 public int getTransparency() { 688 return transparency; 689 } 690 691 public Rectangle getBounds() { 692 return new Rectangle(width, height); 693 } 694 695 @Override 696 public boolean canSourceSendExposures(int x, int y, int w, int h) { 697 return (x < 0 || y < 0 || (x + w) > width || (y + h) > height); 698 } 699 700 public void flush() { 701 /* 702 * We need to invalidate the surface before disposing the native 703 * Drawable and Picture. This way if an application tries to render 704 * to an already flushed XRSurfaceData, we will notice in the 705 * validate() method above that it has been invalidated, and we will 706 * avoid using those native resources that have already been 707 * disposed. 708 */ 709 invalidate(); 710 flushNativeSurface(); 711 } 712 713 /** 714 * Returns destination Image associated with this SurfaceData. 715 */ 716 public Object getDestination() { 717 return offscreenImage; 718 } 719 720 @Override 721 public double getDefaultScaleX() { 722 return scale; 723 } 724 725 @Override 726 public double getDefaultScaleY() { 727 return scale; 728 } 729 } 730 731 public long getGC() { 732 return xgc; 733 } 734 735 public static class LazyPipe extends ValidatePipe { 736 public boolean validate(SunGraphics2D sg2d) { 737 XRSurfaceData xsd = (XRSurfaceData) sg2d.surfaceData; 738 if (!xsd.isXRDrawableValid()) { 739 return false; 740 } 741 xsd.makePipes(); 742 return super.validate(sg2d); 743 } 744 } 745 746 public int getPicture() { 747 return picture; 748 } 749 750 public int getXid() { 751 return xid; 752 } 753 754 public XRGraphicsConfig getGraphicsConfig() { 755 return graphicsConfig; 756 } 757 758 public void setStaticSrcTx(AffineTransform staticSrcTx) { 759 this.staticSrcTx = staticSrcTx; 760 } 761 }