1 /* 2 * Copyright (c) 2011, 2017, 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 { 38 private static native void initIDs(); 39 40 static { 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 68 public static native SurfaceData getSurfaceData(BufferedImage bufImg); 69 70 protected static native void setSurfaceData(BufferedImage bufImg, SurfaceData sData); 71 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 94 public static SurfaceData createData(Raster ras, ColorModel cm) { 95 throw new InternalError("SurfaceData not implemented for Raster/CM"); 96 } 97 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 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 368 public static SurfaceData createDataIC(BufferedImage bImg, SurfaceType sType) { 369 return createDataIC(bImg, sType, bImg.getType()); 370 } 371 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 393 public static SurfaceData createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm) { 394 return createDataSC(bImg, sType, icm, bImg.getType()); 395 } 396 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 420 public static SurfaceData createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank) { 421 return createDataBC(bImg, sType, primaryBank, bImg.getType()); 422 } 423 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 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 450 protected native void initCustomRaster(IntBuffer buffer, int width, int height, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo); 451 452 public Object getLockObject() { 453 return this.lock; 454 } 455 456 // Makes the constructor package private instead of public. 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 */ 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 */ 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 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 550 native boolean xorSurfacePixels(SurfaceData src, int colorXOR, int x, int y, int w, int h); 551 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 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 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 */ 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 */ 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 611 private void syncFromCustom() { 612 613 } 614 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 634 private native void syncToJavaPixels(); 635 636 // we need to refer to rasters often, so cache them 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 }