1 /* 2 * Copyright (c) 2011, 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; 27 28 import java.awt.*; 29 import java.awt.color.*; 30 import java.awt.image.*; 31 import java.nio.*; 32 33 import sun.awt.image.*; 34 import sun.java2d.loops.*; 35 36 public class OSXOffScreenSurfaceData extends OSXSurfaceData // implements RasterListener 37 { initIDs()38 private static native void initIDs(); 39 40 static { initIDs()41 initIDs(); 42 } 43 44 // the image associated with this surface 45 BufferedImage bim; 46 // the image associated with this custom surface 47 BufferedImage bimBackup; 48 // <rdar://problem/4177639> nio based images use ARGB_PRE 49 static DirectColorModel dcmBackup = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, true, DataBuffer.TYPE_INT); 50 51 Object lock; 52 53 // cached rasters for easy access 54 WritableRaster bufImgRaster; 55 SunWritableRaster bufImgSunRaster; 56 57 // these are extra image types we can handle 58 private static final int TYPE_3BYTE_RGB = BufferedImage.TYPE_BYTE_INDEXED + 1; 59 60 // these are for callbacks when pixes have been touched 61 protected ByteBuffer fImageInfo; 62 IntBuffer fImageInfoInt; 63 private static final int kNeedToSyncFromJavaPixelsIndex = 0; 64 private static final int kNativePixelsChangedIndex = 1; 65 private static final int kImageStolenIndex = 2; 66 private static final int kSizeOfParameters = kImageStolenIndex + 1; 67 getSurfaceData(BufferedImage bufImg)68 public static native SurfaceData getSurfaceData(BufferedImage bufImg); 69 setSurfaceData(BufferedImage bufImg, SurfaceData sData)70 protected static native void setSurfaceData(BufferedImage bufImg, SurfaceData sData); 71 createData(BufferedImage bufImg)72 public static SurfaceData createData(BufferedImage bufImg) { 73 /* 74 * if ((bufImg.getWidth() == 32) && (bufImg.getHeight() == 32)) { Thread.dumpStack(); } 75 */ 76 // This could be called from multiple threads. We need to synchronized on the image so that 77 // we can ensure that only one surface data is created per image. (<rdar://4564873>) 78 // Note: Eventually, we should switch to using the same mechanism (CachingSurfaceManager) that Sun uses 79 // <rdar://4563741> 80 synchronized (bufImg) { 81 SurfaceData sData = getSurfaceData(bufImg); 82 if (sData != null) { return sData; } 83 84 OSXOffScreenSurfaceData osData = OSXOffScreenSurfaceData.createNewSurface(bufImg); 85 86 OSXOffScreenSurfaceData.setSurfaceData(bufImg, osData); 87 osData.cacheRasters(bufImg); 88 // osData.setRasterListener(); 89 90 return osData; 91 } 92 } 93 createData(Raster ras, ColorModel cm)94 public static SurfaceData createData(Raster ras, ColorModel cm) { 95 throw new InternalError("SurfaceData not implemented for Raster/CM"); 96 } 97 createNewSurface(BufferedImage bufImg)98 static OSXOffScreenSurfaceData createNewSurface(BufferedImage bufImg) { 99 SurfaceData sData = null; 100 101 ColorModel cm = bufImg.getColorModel(); 102 int type = bufImg.getType(); 103 // REMIND: Check the image type and pick an appropriate subclass 104 switch (type) { 105 case BufferedImage.TYPE_INT_BGR: 106 sData = createDataIC(bufImg, SurfaceType.IntBgr); 107 break; 108 case BufferedImage.TYPE_INT_RGB: 109 sData = createDataIC(bufImg, SurfaceType.IntRgb); 110 break; 111 case BufferedImage.TYPE_INT_ARGB: 112 sData = createDataIC(bufImg, SurfaceType.IntArgb); 113 break; 114 case BufferedImage.TYPE_INT_ARGB_PRE: 115 sData = createDataIC(bufImg, SurfaceType.IntArgbPre); 116 break; 117 case BufferedImage.TYPE_3BYTE_BGR: 118 sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2); 119 break; 120 case BufferedImage.TYPE_4BYTE_ABGR: 121 sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3); 122 break; 123 case BufferedImage.TYPE_4BYTE_ABGR_PRE: 124 sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3); 125 break; 126 case BufferedImage.TYPE_USHORT_565_RGB: 127 sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null); 128 break; 129 case BufferedImage.TYPE_USHORT_555_RGB: 130 sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null); 131 break; 132 case BufferedImage.TYPE_BYTE_INDEXED: { 133 SurfaceType sType; 134 switch (cm.getTransparency()) { 135 case OPAQUE: 136 if (isOpaqueGray((IndexColorModel) cm)) { 137 sType = SurfaceType.Index8Gray; 138 } else { 139 sType = SurfaceType.ByteIndexedOpaque; 140 } 141 break; 142 case BITMASK: 143 sType = SurfaceType.ByteIndexedBm; 144 break; 145 case TRANSLUCENT: 146 sType = SurfaceType.ByteIndexed; 147 break; 148 default: 149 throw new InternalError("Unrecognized transparency"); 150 } 151 sData = createDataBC(bufImg, sType, 0); 152 } 153 break; 154 case BufferedImage.TYPE_BYTE_GRAY: 155 sData = createDataBC(bufImg, SurfaceType.ByteGray, 0); 156 break; 157 case BufferedImage.TYPE_USHORT_GRAY: 158 sData = createDataSC(bufImg, SurfaceType.UshortGray, null); 159 break; 160 case BufferedImage.TYPE_BYTE_BINARY: 161 case BufferedImage.TYPE_CUSTOM: 162 default: { 163 Raster raster = bufImg.getRaster(); 164 165 // we try to fit a custom image into one of the predefined BufferedImages (BufferedImage does that 166 // first, we further refine it here) 167 // we can do that because a pointer in C is a pointer (pixel pointer not dependent on DataBuffer type) 168 SampleModel sm = bufImg.getSampleModel(); 169 SurfaceType sType = SurfaceType.Custom; 170 int transferType = cm.getTransferType(); 171 int pixelSize = cm.getPixelSize(); 172 int numOfComponents = cm.getNumColorComponents(); 173 if ((numOfComponents == 3) && (cm instanceof ComponentColorModel) && (sm instanceof PixelInterleavedSampleModel)) { 174 int[] sizes = cm.getComponentSize(); 175 boolean validsizes = (sizes[0] == 8) && (sizes[1] == 8) && (sizes[2] == 8); 176 int[] offs = ((ComponentSampleModel) sm).getBandOffsets(); 177 int numBands = raster.getNumBands(); 178 boolean bigendian = (offs[0] == numBands - 3) && (offs[1] == numBands - 2) && (offs[2] == numBands - 1); 179 boolean littleendian = (offs[0] == numBands - 1) && (offs[1] == numBands - 2) && (offs[2] == numBands - 3); 180 181 if ((pixelSize == 32) && (transferType == DataBuffer.TYPE_INT)) { 182 if (validsizes && bigendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) { 183 try { 184 sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_ARGB_PRE); 185 } catch (ClassCastException e) { 186 sData = null; 187 } 188 } else if (validsizes && bigendian && cm.hasAlpha() && sizes[3] == 8) { 189 try { 190 sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_ARGB); 191 } catch (ClassCastException e) { 192 sData = null; 193 } 194 } else if (validsizes && littleendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) { 195 try { 196 sData = createDataIC(bufImg, sType, BufferedImage.TYPE_4BYTE_ABGR_PRE); 197 } catch (ClassCastException e) { 198 sData = null; 199 } 200 } else if (validsizes && littleendian && cm.hasAlpha() && sizes[3] == 8) { 201 try { 202 sData = createDataIC(bufImg, sType, BufferedImage.TYPE_4BYTE_ABGR); 203 } catch (ClassCastException e) { 204 sData = null; 205 } 206 } else if (validsizes && bigendian) { 207 try { 208 sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_RGB); 209 } catch (ClassCastException e) { 210 sData = null; 211 } 212 } 213 } else if ((pixelSize == 32) && (transferType == DataBuffer.TYPE_BYTE)) { 214 if (validsizes && bigendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) { 215 try { 216 sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_ARGB_PRE); 217 } catch (ClassCastException e) { 218 sData = null; 219 } 220 } 221 if (validsizes && bigendian && cm.hasAlpha() && sizes[3] == 8) { 222 try { 223 sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_ARGB); 224 } catch (ClassCastException e) { 225 sData = null; 226 } 227 } else if (validsizes && littleendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) { 228 try { 229 sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_4BYTE_ABGR_PRE); 230 } catch (ClassCastException e) { 231 sData = null; 232 } 233 } else if (validsizes && littleendian && cm.hasAlpha() && sizes[3] == 8) { 234 try { 235 sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_4BYTE_ABGR); 236 } catch (ClassCastException e) { 237 sData = null; 238 } 239 } else if (validsizes && littleendian) { 240 try { 241 sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_BGR); 242 } catch (ClassCastException e) { 243 sData = null; 244 } 245 } else if (validsizes && bigendian) { 246 try { 247 sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_RGB); 248 } catch (ClassCastException e) { 249 sData = null; 250 } 251 } 252 } else if ((pixelSize == 24) && (transferType == DataBuffer.TYPE_INT)) { 253 if (validsizes && bigendian) { 254 try { 255 sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_RGB); 256 } catch (ClassCastException e) { 257 sData = null; 258 } 259 } else if (validsizes && littleendian) { 260 try { 261 sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_BGR); 262 } catch (ClassCastException e) { 263 sData = null; 264 } 265 } 266 } else if ((pixelSize == 24) && (transferType == DataBuffer.TYPE_BYTE)) { 267 if (validsizes && bigendian) { 268 try { 269 sData = createDataBC(bufImg, sType, 0, TYPE_3BYTE_RGB); 270 } catch (ClassCastException e) { 271 sData = null; 272 } 273 } else if (validsizes && littleendian) { 274 try { 275 sData = createDataBC(bufImg, sType, 0, BufferedImage.TYPE_3BYTE_BGR); 276 } catch (ClassCastException e) { 277 sData = null; 278 } 279 } 280 } else if ((pixelSize == 16) && (transferType == DataBuffer.TYPE_USHORT)) { 281 validsizes = (sizes[0] == 5) && (sizes[1] == 6) && (sizes[2] == 5); 282 if (validsizes && bigendian) { 283 try { 284 sData = createDataSC(bufImg, sType, null, BufferedImage.TYPE_USHORT_565_RGB); 285 } catch (ClassCastException e) { 286 sData = null; 287 } 288 } 289 } else if ((pixelSize == 16) && (transferType == DataBuffer.TYPE_BYTE)) { 290 validsizes = (sizes[0] == 5) && (sizes[1] == 6) && (sizes[2] == 5); 291 if (validsizes && bigendian) { 292 try { 293 sData = createDataBC(bufImg, sType, 1, BufferedImage.TYPE_USHORT_565_RGB); 294 } catch (ClassCastException e) { 295 sData = null; 296 } 297 } 298 } else if ((pixelSize == 15) && (transferType == DataBuffer.TYPE_USHORT)) { 299 validsizes = (sizes[0] == 5) && (sizes[1] == 5) && (sizes[2] == 5); 300 if (validsizes && bigendian) { 301 try { 302 sData = createDataSC(bufImg, sType, null, BufferedImage.TYPE_USHORT_555_RGB); 303 } catch (ClassCastException e) { 304 sData = null; 305 } 306 } 307 } else if ((pixelSize == 15) && (transferType == DataBuffer.TYPE_BYTE)) { 308 validsizes = (sizes[0] == 5) && (sizes[1] == 5) && (sizes[2] == 5); 309 if (validsizes && bigendian) { 310 try { 311 sData = createDataBC(bufImg, sType, 1, BufferedImage.TYPE_USHORT_555_RGB); 312 } catch (ClassCastException e) { 313 sData = null; 314 } 315 } 316 } 317 } 318 } 319 break; 320 } 321 322 // we failed to match 323 if (sData == null) { 324 sData = new OSXOffScreenSurfaceData(bufImg, SurfaceType.Custom); 325 OSXOffScreenSurfaceData offsd = (OSXOffScreenSurfaceData) sData; 326 327 // 2004_03_26 cmc: We used to use createCompatibleImage here. Now that createCompatibleImage returns 328 // an INT_ARGB_PRE instead of an NIO-based image, we need to explicitly create an NIO-based image. 329 IntegerNIORaster backupRaster = (IntegerNIORaster) IntegerNIORaster.createNIORaster(bufImg.getWidth(), bufImg.getHeight(), dcmBackup.getMasks(), null); 330 offsd.bimBackup = new BufferedImage(dcmBackup, backupRaster, dcmBackup.isAlphaPremultiplied(), null); 331 332 // the trick that makes it work - assign the raster from backup to the surface data of the original image 333 offsd.initCustomRaster(backupRaster.getBuffer(), 334 backupRaster.getWidth(), 335 backupRaster.getHeight(), 336 offsd.fGraphicsStates, 337 offsd.fGraphicsStatesObject, 338 offsd.fImageInfo); 339 340 //offsd.checkIfLazyPixelConversionDisabled(); 341 offsd.fImageInfoInt.put(kImageStolenIndex, 1); 342 } 343 344 return (OSXOffScreenSurfaceData) sData; 345 } 346 createDataIC(BufferedImage bImg, SurfaceType sType, int iType)347 private static SurfaceData createDataIC(BufferedImage bImg, SurfaceType sType, int iType) { 348 OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType); 349 350 IntegerComponentRaster icRaster = (IntegerComponentRaster) bImg.getRaster(); 351 offsd.initRaster(icRaster.getDataStorage(), 352 icRaster.getDataOffset(0) * 4, 353 icRaster.getWidth(), 354 icRaster.getHeight(), 355 icRaster.getPixelStride() * 4, 356 icRaster.getScanlineStride() * 4, 357 null, 358 iType, 359 offsd.fGraphicsStates, 360 offsd.fGraphicsStatesObject, 361 offsd.fImageInfo); 362 363 // offsd.checkIfLazyPixelConversionDisabled(); 364 offsd.fImageInfoInt.put(kImageStolenIndex, 1); 365 return offsd; 366 } 367 createDataIC(BufferedImage bImg, SurfaceType sType)368 public static SurfaceData createDataIC(BufferedImage bImg, SurfaceType sType) { 369 return createDataIC(bImg, sType, bImg.getType()); 370 } 371 createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm, int iType)372 private static SurfaceData createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm, int iType) { 373 OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType); 374 375 ShortComponentRaster scRaster = (ShortComponentRaster) bImg.getRaster(); 376 offsd.initRaster(scRaster.getDataStorage(), 377 scRaster.getDataOffset(0) * 2, 378 scRaster.getWidth(), 379 scRaster.getHeight(), 380 scRaster.getPixelStride() * 2, 381 scRaster.getScanlineStride() * 2, 382 icm, 383 iType, 384 offsd.fGraphicsStates, 385 offsd.fGraphicsStatesObject, 386 offsd.fImageInfo); 387 388 //offsd.checkIfLazyPixelConversionDisabled(); 389 offsd.fImageInfoInt.put(kImageStolenIndex, 1); 390 return offsd; 391 } 392 createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm)393 public static SurfaceData createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm) { 394 return createDataSC(bImg, sType, icm, bImg.getType()); 395 } 396 createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank, int iType)397 private static SurfaceData createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank, int iType) { 398 OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType); 399 400 ByteComponentRaster bcRaster = (ByteComponentRaster) bImg.getRaster(); 401 ColorModel cm = bImg.getColorModel(); 402 IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm : null); 403 offsd.initRaster(bcRaster.getDataStorage(), 404 bcRaster.getDataOffset(primaryBank), 405 bcRaster.getWidth(), 406 bcRaster.getHeight(), 407 bcRaster.getPixelStride(), 408 bcRaster.getScanlineStride(), 409 icm, 410 iType, 411 offsd.fGraphicsStates, 412 offsd.fGraphicsStatesObject, 413 offsd.fImageInfo); 414 415 offsd.fImageInfoInt.put(kImageStolenIndex, 1); 416 417 return offsd; 418 } 419 createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank)420 public static SurfaceData createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank) { 421 return createDataBC(bImg, sType, primaryBank, bImg.getType()); 422 } 423 createDataBP(BufferedImage bImg, SurfaceType sType, int iType)424 private static SurfaceData createDataBP(BufferedImage bImg, SurfaceType sType, int iType) { 425 OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType); 426 427 BytePackedRaster bpRaster = (BytePackedRaster) bImg.getRaster(); 428 ColorModel cm = bImg.getColorModel(); 429 IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm : null); 430 offsd.initRaster(bpRaster.getDataStorage(), 431 bpRaster.getDataBitOffset(), // in bits, NOT bytes! (needs special attention in native 432 // code!) 433 bpRaster.getWidth(), 434 bpRaster.getHeight(), 435 bpRaster.getPixelBitStride(), 436 bpRaster.getScanlineStride() * 8, 437 icm, 438 iType, 439 offsd.fGraphicsStates, 440 offsd.fGraphicsStatesObject, 441 offsd.fImageInfo); 442 443 //offsd.checkIfLazyPixelConversionDisabled(); 444 offsd.fImageInfoInt.put(kImageStolenIndex, 1); 445 return offsd; 446 } 447 initRaster(Object theArray, int offset, int width, int height, int pixStr, int scanStr, IndexColorModel icm, int type, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo)448 protected native void initRaster(Object theArray, int offset, int width, int height, int pixStr, int scanStr, IndexColorModel icm, int type, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo); 449 initCustomRaster(IntBuffer buffer, int width, int height, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo)450 protected native void initCustomRaster(IntBuffer buffer, int width, int height, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo); 451 getLockObject()452 public Object getLockObject() { 453 return this.lock; 454 } 455 456 // Makes the constructor package private instead of public. OSXOffScreenSurfaceData(BufferedImage bufImg, SurfaceType sType)457 OSXOffScreenSurfaceData(BufferedImage bufImg, SurfaceType sType) { 458 super(sType, bufImg.getColorModel()); 459 setBounds(0, 0, bufImg.getWidth(), bufImg.getHeight()); 460 461 this.bim = bufImg; 462 463 this.fImageInfo = ByteBuffer.allocateDirect(4 * kSizeOfParameters); 464 this.fImageInfo.order(ByteOrder.nativeOrder()); 465 this.fImageInfoInt = this.fImageInfo.asIntBuffer(); 466 467 this.fImageInfoInt.put(kNeedToSyncFromJavaPixelsIndex, 1); // need to sync from Java the very first time 468 this.fImageInfoInt.put(kNativePixelsChangedIndex, 0); 469 this.fImageInfoInt.put(kImageStolenIndex, 0); 470 471 this.lock = new Object(); 472 } 473 474 /** 475 * Performs a copyArea within this surface. 476 */ copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy)477 public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) { 478 // <rdar://problem/4488745> For the Sun2D renderer we should rely on the implementation of the super class. 479 // BufImageSurfaceData.java doesn't have an implementation of copyArea() and relies on the super class. 480 481 if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) { 482 return false; 483 } 484 485 // reset the clip (this is how it works on windows) 486 // we actually can handle a case with any clips but windows ignores the light clip 487 Shape clip = sg2d.getClip(); 488 sg2d.setClip(getBounds()); 489 490 // clip copyArea 491 Rectangle clippedCopyAreaRect = clipCopyArea(sg2d, x, y, w, h, dx, dy); 492 if (clippedCopyAreaRect == null) { 493 // clipped out 494 return true; 495 } 496 497 // the rectangle returned from clipCopyArea() is in the coordinate space 498 // of the surface (image) 499 x = clippedCopyAreaRect.x; 500 y = clippedCopyAreaRect.y; 501 w = clippedCopyAreaRect.width; 502 h = clippedCopyAreaRect.height; 503 504 // copy (dst coordinates are in the coord space of the graphics2d, and 505 // src coordinates are in the coordinate space of the image) 506 // sg2d.drawImage expects the destination rect to be in the coord space 507 // of the graphics2d. <rdar://3746194> (vm) 508 // we need to substract the transX and transY to move it 509 // to the coordinate space of the graphics2d. 510 int dstX = x + dx - sg2d.transX; 511 int dstY = y + dy - sg2d.transY; 512 sg2d.drawImage(this.bim, dstX, dstY, dstX + w, dstY + h, 513 x, y, x + w, y + h, null); 514 515 // restore the clip 516 sg2d.setClip(clip); 517 518 return true; 519 } 520 521 /** 522 * Performs a copyarea from this surface to a buffered image. If null is passed in for the image a new image will be 523 * created. 524 * 525 * Only used by compositor code (private API) 526 */ copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage dstImage)527 public BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage dstImage) { 528 // create the destination image if needed 529 if (dstImage == null) { 530 dstImage = getDeviceConfiguration().createCompatibleImage(w, h); 531 } 532 533 // copy 534 Graphics g = dstImage.createGraphics(); 535 g.drawImage(this.bim, 0, 0, w, h, x, y, x + w, y + h, null); 536 g.dispose(); 537 538 return dstImage; 539 } 540 xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR)541 public boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR) { 542 543 int type = this.bim.getType(); 544 545 if ((type == BufferedImage.TYPE_INT_ARGB_PRE) || (type == BufferedImage.TYPE_INT_ARGB) || (type == BufferedImage.TYPE_INT_RGB)) { return xorSurfacePixels(createData(srcPixels), colorXOR, x, y, w, h); } 546 547 return false; 548 } 549 xorSurfacePixels(SurfaceData src, int colorXOR, int x, int y, int w, int h)550 native boolean xorSurfacePixels(SurfaceData src, int colorXOR, int x, int y, int w, int h); 551 clearRect(BufferedImage bim, int w, int h)552 public void clearRect(BufferedImage bim, int w, int h) { 553 OSXOffScreenSurfaceData offsd = (OSXOffScreenSurfaceData) (OSXOffScreenSurfaceData.createData(bim)); 554 // offsd.clear(); 555 if (offsd.clearSurfacePixels(w, h) == false) { 556 Graphics2D g = bim.createGraphics(); 557 g.setComposite(AlphaComposite.Clear); 558 g.fillRect(0, 0, w, h); 559 g.dispose(); 560 } 561 } 562 clearSurfacePixels(int w, int h)563 native boolean clearSurfacePixels(int w, int h); 564 565 // 04/06/04 cmc: radr://3612381 Graphics.drawImage ignores bgcolor parameter. 566 // getCopyWithBgColor returns a new version of an image, drawn with a background 567 // color. Called by blitImage in OSXSurfaceData.java. 568 BufferedImage copyWithBgColor_cache = null; 569 getCopyWithBgColor(Color bgColor)570 public SurfaceData getCopyWithBgColor(Color bgColor) { 571 int bimW = this.bim.getWidth(); 572 int bimH = this.bim.getHeight(); 573 574 if ((this.copyWithBgColor_cache == null) 575 || (this.copyWithBgColor_cache.getWidth() < bimW) || (this.copyWithBgColor_cache.getHeight() < bimH)) { 576 GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); 577 this.copyWithBgColor_cache = gc.createCompatibleImage(bimW, bimH); 578 } 579 580 Graphics g2 = this.copyWithBgColor_cache.createGraphics(); 581 g2.setColor(bgColor); 582 g2.fillRect(0, 0, bimW, bimH); 583 g2.drawImage(this.bim, 0, 0, bimW, bimH, null); 584 g2.dispose(); 585 586 return getSurfaceData(this.copyWithBgColor_cache); 587 } 588 589 /** 590 * Invoked before the raster's contents are to be read (via one of the modifier methods in Raster such as 591 * getPixel()) 592 */ rasterRead()593 public void rasterRead() { 594 if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) { 595 syncToJavaPixels(); 596 } 597 } 598 599 /** 600 * Invoked before the raster's contents are to be written to (via one of the modifier methods in Raster such as 601 * setPixel()) 602 */ rasterWrite()603 public void rasterWrite() { 604 if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) { 605 syncToJavaPixels(); 606 } 607 608 fImageInfoInt.put(kNeedToSyncFromJavaPixelsIndex, 1); // the pixels will change 609 } 610 syncFromCustom()611 private void syncFromCustom() { 612 613 } 614 syncToCustom()615 private void syncToCustom() { 616 617 } 618 // /** 619 // * Invoked when the raster's contents will be taken (via the Raster.getDataBuffer() method) 620 // */ 621 // public void rasterStolen() { 622 // fImageInfoInt.put(kImageStolenIndex, 1); // this means we must convert between Java and native pixels every 623 // // single primitive! (very expensive) 624 // if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) { 625 // syncToJavaPixels(); 626 // } 627 // 628 // // we know the pixels have been stolen, no need to listen for changes any more 629 //// if (this.bufImgSunRaster != null) { 630 //// this.bufImgSunRaster.setRasterListener(null); 631 //// } 632 // } 633 syncToJavaPixels()634 private native void syncToJavaPixels(); 635 636 // we need to refer to rasters often, so cache them cacheRasters(BufferedImage bim)637 void cacheRasters(BufferedImage bim) { 638 this.bufImgRaster = bim.getRaster(); 639 if (this.bufImgRaster instanceof SunWritableRaster) { 640 this.bufImgSunRaster = (SunWritableRaster) this.bufImgRaster; 641 } 642 } 643 644 // void setRasterListener() { 645 // if (this.bufImgSunRaster != null) { 646 // this.bufImgSunRaster.setRasterListener(this); 647 // 648 // Raster parentRaster = this.bufImgSunRaster.getParent(); 649 // if (parentRaster != null) { 650 // if (parentRaster instanceof SunWritableRaster) { 651 // // mark subimages stolen to turn off lazy pixel conversion (gznote: can we do better here?) 652 // ((SunWritableRaster) parentRaster).notifyStolen(); 653 // } 654 // rasterStolen(); 655 // } 656 // } else { 657 // // it's a custom image (non-natively supported) and we can not set a raster listener 658 // // so mark the image as stolen - this will turn off LazyPixelConversion optimization (slow, but correct) 659 // rasterStolen(); 660 // } 661 // } 662 } 663