1 /* 2 * Copyright (c) 1995, 2010, 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.awt.image; 27 28 import java.awt.Color; 29 import java.awt.Graphics; 30 import java.awt.Transparency; 31 import java.awt.AWTException; 32 import java.awt.Rectangle; 33 import java.awt.image.BufferedImage; 34 import java.awt.image.ColorModel; 35 import java.awt.image.DirectColorModel; 36 import java.awt.image.IndexColorModel; 37 import java.awt.image.ImageConsumer; 38 import java.awt.image.ImageObserver; 39 import sun.awt.image.ByteComponentRaster; 40 import sun.awt.image.IntegerComponentRaster; 41 import java.awt.image.Raster; 42 import java.awt.image.WritableRaster; 43 import java.awt.image.DataBuffer; 44 import java.awt.image.DataBufferInt; 45 import java.awt.Graphics2D; 46 import java.awt.geom.AffineTransform; 47 import sun.awt.image.ImageWatched; 48 import java.util.Hashtable; 49 50 public class ImageRepresentation extends ImageWatched implements ImageConsumer 51 { 52 InputStreamImageSource src; 53 ToolkitImage image; 54 int tag; 55 56 long pData; // used by windows native code only -- internal state REMIND ATTN @@ 57 58 int width = -1; 59 int height = -1; 60 int hints; 61 62 int availinfo; 63 64 Rectangle newbits; 65 66 BufferedImage bimage; 67 WritableRaster biRaster; 68 protected ColorModel cmodel; 69 ColorModel srcModel = null; 70 int[] srcLUT = null; 71 int srcLUTtransIndex = -1; 72 int numSrcLUT = 0; 73 boolean forceCMhint; 74 int sstride; 75 boolean isDefaultBI = false; 76 boolean isSameCM = false; 77 78 private native static void initIDs(); 79 80 static { 81 /* ensure that the necessary native libraries are loaded */ 82 NativeLibLoader.loadLibraries(); 83 initIDs(); 84 } 85 86 /** 87 * Create an ImageRepresentation for the given Image. The 88 * width and height are unknown at this point. The color 89 * model is a hint as to the color model to use when creating 90 * the buffered image. If null, the src color model will 91 * be used. 92 */ 93 public ImageRepresentation(ToolkitImage im, ColorModel cmodel, boolean 94 forceCMhint) { 95 image = im; 96 97 if (image.getSource() instanceof InputStreamImageSource) { 98 src = (InputStreamImageSource) image.getSource(); 99 } 100 101 setColorModel(cmodel); 102 103 this.forceCMhint = forceCMhint; 104 } 105 106 /* REMIND: Only used for Frame.setIcon - should use ImageWatcher instead */ 107 public synchronized void reconstruct(int flags) { 108 if (src != null) { 109 src.checkSecurity(null, false); 110 } 111 int missinginfo = flags & ~availinfo; 112 if ((availinfo & ImageObserver.ERROR) == 0 && missinginfo != 0) { 113 numWaiters++; 114 try { 115 startProduction(); 116 missinginfo = flags & ~availinfo; 117 while ((availinfo & ImageObserver.ERROR) == 0 && 118 missinginfo != 0) 119 { 120 try { 121 wait(); 122 } catch (InterruptedException e) { 123 Thread.currentThread().interrupt(); 124 return; 125 } 126 missinginfo = flags & ~availinfo; 127 } 128 } finally { 129 decrementWaiters(); 130 } 131 } 132 } 133 134 public void setDimensions(int w, int h) { 135 if (src != null) { 136 src.checkSecurity(null, false); 137 } 138 139 image.setDimensions(w, h); 140 141 newInfo(image, (ImageObserver.WIDTH | ImageObserver.HEIGHT), 142 0, 0, w, h); 143 144 if (w <= 0 || h <= 0) { 145 imageComplete(ImageConsumer.IMAGEERROR); 146 return; 147 } 148 149 if (width != w || height != h) { 150 // dimension mismatch => trigger recreation of the buffer 151 bimage = null; 152 } 153 154 width = w; 155 height = h; 156 157 availinfo |= ImageObserver.WIDTH | ImageObserver.HEIGHT; 158 } 159 160 public int getWidth() { 161 return width; 162 } 163 164 public int getHeight() { 165 return height; 166 } 167 168 ColorModel getColorModel() { 169 return cmodel; 170 } 171 172 BufferedImage getBufferedImage() { 173 return bimage; 174 } 175 176 /** 177 * Returns the BufferedImage that will be used as the representation of 178 * the pixel data. Subclasses can override this method to return 179 * platform specific subclasses of BufferedImage that may or may not be 180 * accelerated. 181 * 182 * It is subclass' responsibility to propagate acceleration priority 183 * to the newly created image. 184 */ 185 protected BufferedImage createImage(ColorModel cm, 186 WritableRaster raster, 187 boolean isRasterPremultiplied, 188 Hashtable properties) 189 { 190 BufferedImage bi = 191 new BufferedImage(cm, raster, isRasterPremultiplied, null); 192 bi.setAccelerationPriority(image.getAccelerationPriority()); 193 return bi; 194 } 195 196 public void setProperties(Hashtable<?,?> props) { 197 if (src != null) { 198 src.checkSecurity(null, false); 199 } 200 image.setProperties(props); 201 newInfo(image, ImageObserver.PROPERTIES, 0, 0, 0, 0); 202 } 203 204 public void setColorModel(ColorModel model) { 205 if (src != null) { 206 src.checkSecurity(null, false); 207 } 208 srcModel = model; 209 210 // Check to see if model is INT_RGB 211 if (model instanceof IndexColorModel) { 212 if (model.getTransparency() == model.TRANSLUCENT) { 213 // REMIND: 214 // Probably need to composite anyway so force ARGB 215 cmodel = ColorModel.getRGBdefault(); 216 srcLUT = null; 217 } 218 else { 219 IndexColorModel icm = (IndexColorModel) model; 220 numSrcLUT = icm.getMapSize(); 221 srcLUT = new int[Math.max(numSrcLUT, 256)]; 222 icm.getRGBs(srcLUT); 223 srcLUTtransIndex = icm.getTransparentPixel(); 224 cmodel = model; 225 } 226 } 227 else { 228 if (cmodel == null) { 229 cmodel = model; 230 srcLUT = null; 231 } 232 else if (model instanceof DirectColorModel) { 233 // If it is INT_RGB or INT_ARGB, use the model 234 DirectColorModel dcm = (DirectColorModel) model; 235 if ((dcm.getRedMask() == 0xff0000) && 236 (dcm.getGreenMask() == 0xff00) && 237 (dcm.getBlueMask() == 0x00ff)) { 238 cmodel = model; 239 srcLUT = null; 240 } 241 } 242 } 243 244 isSameCM = (cmodel == model); 245 } 246 247 void createBufferedImage() { 248 // REMIND: Be careful! Is this called everytime there is a 249 // startProduction? We only want to call it if it is new or 250 // there is an error 251 isDefaultBI = false; 252 try { 253 biRaster = cmodel.createCompatibleWritableRaster(width, height); 254 bimage = createImage(cmodel, biRaster, 255 cmodel.isAlphaPremultiplied(), null); 256 } catch (Exception e) { 257 // Create a default image 258 cmodel = ColorModel.getRGBdefault(); 259 biRaster = cmodel.createCompatibleWritableRaster(width, height); 260 bimage = createImage(cmodel, biRaster, false, null); 261 } 262 int type = bimage.getType(); 263 264 if ((cmodel == ColorModel.getRGBdefault()) || 265 (type == BufferedImage.TYPE_INT_RGB) || 266 (type == BufferedImage.TYPE_INT_ARGB_PRE)) { 267 isDefaultBI = true; 268 } 269 else if (cmodel instanceof DirectColorModel) { 270 DirectColorModel dcm = (DirectColorModel) cmodel; 271 if (dcm.getRedMask() == 0xff0000 && 272 dcm.getGreenMask() == 0xff00 && 273 dcm.getBlueMask() == 0xff) { 274 isDefaultBI = true; 275 } 276 } 277 } 278 279 private void convertToRGB() { 280 int w = bimage.getWidth(); 281 int h = bimage.getHeight(); 282 int size = w*h; 283 284 DataBufferInt dbi = new DataBufferInt(size); 285 // Note that stealData() requires a markDirty() afterwards 286 // since we modify the data in it. 287 int newpixels[] = SunWritableRaster.stealData(dbi, 0); 288 if (cmodel instanceof IndexColorModel && 289 biRaster instanceof ByteComponentRaster && 290 biRaster.getNumDataElements() == 1) 291 { 292 ByteComponentRaster bct = (ByteComponentRaster) biRaster; 293 byte[] data = bct.getDataStorage(); 294 int coff = bct.getDataOffset(0); 295 for (int i=0; i < size; i++) { 296 newpixels[i] = srcLUT[data[coff+i]&0xff]; 297 } 298 } 299 else { 300 Object srcpixels = null; 301 int off=0; 302 for (int y=0; y < h; y++) { 303 for (int x=0; x < w; x++) { 304 srcpixels=biRaster.getDataElements(x, y, srcpixels); 305 newpixels[off++] = cmodel.getRGB(srcpixels); 306 } 307 } 308 } 309 // We modified the data array directly above so mark it as dirty now... 310 SunWritableRaster.markDirty(dbi); 311 312 isSameCM = false; 313 cmodel = ColorModel.getRGBdefault(); 314 315 int bandMasks[] = {0x00ff0000, 316 0x0000ff00, 317 0x000000ff, 318 0xff000000}; 319 320 biRaster = Raster.createPackedRaster(dbi,w,h,w, 321 bandMasks,null); 322 323 bimage = createImage(cmodel, biRaster, 324 cmodel.isAlphaPremultiplied(), null); 325 srcLUT = null; 326 isDefaultBI = true; 327 } 328 329 public void setHints(int h) { 330 if (src != null) { 331 src.checkSecurity(null, false); 332 } 333 hints = h; 334 } 335 336 private native void setICMpixels(int x, int y, int w, int h, int[] lut, 337 byte[] pix, int off, int scansize, 338 IntegerComponentRaster ict); 339 private native int setDiffICM(int x, int y, int w, int h, int[] lut, 340 int transPix, int numLut, IndexColorModel icm, 341 byte[] pix, int off, int scansize, 342 ByteComponentRaster bct, int chanOff); 343 static boolean s_useNative = true; 344 345 public void setPixels(int x, int y, int w, int h, 346 ColorModel model, 347 byte pix[], int off, int scansize) { 348 int lineOff=off; 349 int poff; 350 int[] newLUT=null; 351 352 if (src != null) { 353 src.checkSecurity(null, false); 354 } 355 356 // REMIND: What if the model doesn't fit in default color model? 357 synchronized (this) { 358 if (bimage == null) { 359 if (cmodel == null) { 360 cmodel = model; 361 } 362 createBufferedImage(); 363 } 364 365 if (w <= 0 || h <= 0) { 366 return; 367 } 368 369 int biWidth = biRaster.getWidth(); 370 int biHeight = biRaster.getHeight(); 371 372 int x1 = x+w; // Overflow protection below 373 int y1 = y+h; // Overflow protection below 374 if (x < 0) { 375 off -= x; 376 x = 0; 377 } else if (x1 < 0) { 378 x1 = biWidth; // Must be overflow 379 } 380 if (y < 0) { 381 off -= y*scansize; 382 y = 0; 383 } else if (y1 < 0) { 384 y1 = biHeight; // Must be overflow 385 } 386 if (x1 > biWidth) { 387 x1 = biWidth; 388 } 389 if (y1 > biHeight) { 390 y1 = biHeight; 391 } 392 if (x >= x1 || y >= y1) { 393 return; 394 } 395 // x,y,x1,y1 are all >= 0, so w,h must be >= 0 396 w = x1-x; 397 h = y1-y; 398 // off is first pixel read so it must be in bounds 399 if (off < 0 || off >= pix.length) { 400 // They overflowed their own array 401 throw new ArrayIndexOutOfBoundsException("Data offset out of bounds."); 402 } 403 // pix.length and off are >= 0 so remainder >= 0 404 int remainder = pix.length - off; 405 if (remainder < w) { 406 // They overflowed their own array 407 throw new ArrayIndexOutOfBoundsException("Data array is too short."); 408 } 409 int num; 410 if (scansize < 0) { 411 num = (off / -scansize) + 1; 412 } else if (scansize > 0) { 413 num = ((remainder-w) / scansize) + 1; 414 } else { 415 num = h; 416 } 417 if (h > num) { 418 // They overflowed their own array. 419 throw new ArrayIndexOutOfBoundsException("Data array is too short."); 420 } 421 422 if (isSameCM && (cmodel != model) && (srcLUT != null) && 423 (model instanceof IndexColorModel) && 424 (biRaster instanceof ByteComponentRaster)) 425 { 426 IndexColorModel icm = (IndexColorModel) model; 427 ByteComponentRaster bct = (ByteComponentRaster) biRaster; 428 int numlut = numSrcLUT; 429 if (setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex, 430 numSrcLUT, icm, 431 pix, off, scansize, bct, 432 bct.getDataOffset(0)) == 0) { 433 convertToRGB(); 434 } 435 else { 436 // Note that setDiffICM modified the raster directly 437 // so we must mark it as changed 438 bct.markDirty(); 439 if (numlut != numSrcLUT) { 440 boolean hasAlpha = icm.hasAlpha(); 441 if (srcLUTtransIndex != -1) { 442 hasAlpha = true; 443 } 444 int nbits = icm.getPixelSize(); 445 icm = new IndexColorModel(nbits, 446 numSrcLUT, srcLUT, 447 0, hasAlpha, 448 srcLUTtransIndex, 449 (nbits > 8 450 ? DataBuffer.TYPE_USHORT 451 : DataBuffer.TYPE_BYTE)); 452 cmodel = icm; 453 bimage = createImage(icm, bct, false, null); 454 } 455 return; 456 } 457 } 458 459 if (isDefaultBI) { 460 int pixel; 461 IntegerComponentRaster iraster = 462 (IntegerComponentRaster) biRaster; 463 if (srcLUT != null && model instanceof IndexColorModel) { 464 if (model != srcModel) { 465 // Fill in the new lut 466 ((IndexColorModel)model).getRGBs(srcLUT); 467 srcModel = model; 468 } 469 470 if (s_useNative) { 471 // Note that setICMpixels modifies the raster directly 472 // so we must mark it as changed afterwards 473 setICMpixels(x, y, w, h, srcLUT, pix, off, scansize, 474 iraster); 475 iraster.markDirty(); 476 } 477 else { 478 int[] storage = new int[w*h]; 479 int soff = 0; 480 // It is an IndexColorModel 481 for (int yoff=0; yoff < h; yoff++, 482 lineOff += scansize) { 483 poff = lineOff; 484 for (int i=0; i < w; i++) { 485 storage[soff++] = srcLUT[pix[poff++]&0xff]; 486 } 487 } 488 iraster.setDataElements(x, y, w, h, storage); 489 } 490 } 491 else { 492 int[] storage = new int[w]; 493 for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) { 494 poff = lineOff; 495 for (int i=0; i < w; i++) { 496 storage[i] = model.getRGB(pix[poff++]&0xff); 497 } 498 iraster.setDataElements(x, yoff, w, 1, storage); 499 } 500 availinfo |= ImageObserver.SOMEBITS; 501 } 502 } 503 else if ((cmodel == model) && 504 (biRaster instanceof ByteComponentRaster) && 505 (biRaster.getNumDataElements() == 1)){ 506 ByteComponentRaster bt = (ByteComponentRaster) biRaster; 507 if (off == 0 && scansize == w) { 508 bt.putByteData(x, y, w, h, pix); 509 } 510 else { 511 byte[] bpix = new byte[w]; 512 poff = off; 513 for (int yoff=y; yoff < y+h; yoff++) { 514 System.arraycopy(pix, poff, bpix, 0, w); 515 bt.putByteData(x, yoff, w, 1, bpix); 516 poff += scansize; 517 } 518 } 519 } 520 else { 521 for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) { 522 poff = lineOff; 523 for (int xoff=x; xoff < x+w; xoff++) { 524 bimage.setRGB(xoff, yoff, 525 model.getRGB(pix[poff++]&0xff)); 526 } 527 } 528 availinfo |= ImageObserver.SOMEBITS; 529 } 530 } 531 532 if ((availinfo & ImageObserver.FRAMEBITS) == 0) { 533 newInfo(image, ImageObserver.SOMEBITS, x, y, w, h); 534 } 535 } 536 537 538 public void setPixels(int x, int y, int w, int h, ColorModel model, 539 int pix[], int off, int scansize) 540 { 541 int lineOff=off; 542 int poff; 543 544 if (src != null) { 545 src.checkSecurity(null, false); 546 } 547 548 // REMIND: What if the model doesn't fit in default color model? 549 synchronized (this) { 550 if (bimage == null) { 551 if (cmodel == null) { 552 cmodel = model; 553 } 554 createBufferedImage(); 555 } 556 557 int[] storage = new int[w]; 558 int yoff; 559 int pixel; 560 561 if (cmodel instanceof IndexColorModel) { 562 // REMIND: Right now we don't support writing back into ICM 563 // images. 564 convertToRGB(); 565 } 566 567 if ((model == cmodel) && 568 (biRaster instanceof IntegerComponentRaster)) { 569 IntegerComponentRaster iraster = 570 (IntegerComponentRaster) biRaster; 571 572 if (off == 0 && scansize == w) { 573 iraster.setDataElements(x, y, w, h, pix); 574 } 575 else { 576 // Need to pack the data 577 for (yoff=y; yoff < y+h; yoff++, lineOff+=scansize) { 578 System.arraycopy(pix, lineOff, storage, 0, w); 579 iraster.setDataElements(x, yoff, w, 1, storage); 580 } 581 } 582 } 583 else { 584 if (model.getTransparency() != model.OPAQUE && 585 cmodel.getTransparency() == cmodel.OPAQUE) { 586 convertToRGB(); 587 } 588 589 if (isDefaultBI) { 590 IntegerComponentRaster iraster = 591 (IntegerComponentRaster) biRaster; 592 int[] data = iraster.getDataStorage(); 593 if (cmodel.equals(model)) { 594 int sstride = iraster.getScanlineStride(); 595 int doff = y*sstride + x; 596 for (yoff=0; yoff < h; yoff++, lineOff += scansize) { 597 System.arraycopy(pix, lineOff, data, doff, w); 598 doff += sstride; 599 } 600 // Note: manual modification of pixels, mark the 601 // raster as changed 602 iraster.markDirty(); 603 } 604 else { 605 for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) { 606 poff = lineOff; 607 for (int i=0; i < w; i++) { 608 storage[i]=model.getRGB(pix[poff++]); 609 } 610 iraster.setDataElements(x, yoff, w, 1, storage); 611 } 612 } 613 614 availinfo |= ImageObserver.SOMEBITS; 615 } 616 else { 617 Object tmp = null; 618 619 for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) { 620 poff = lineOff; 621 for (int xoff=x; xoff < x+w; xoff++) { 622 pixel = model.getRGB(pix[poff++]); 623 tmp = cmodel.getDataElements(pixel,tmp); 624 biRaster.setDataElements(xoff, yoff,tmp); 625 } 626 } 627 availinfo |= ImageObserver.SOMEBITS; 628 } 629 } 630 } 631 632 // Can't do this here since we might need to transform/clip 633 // the region 634 if (((availinfo & ImageObserver.FRAMEBITS) == 0)) { 635 newInfo(image, ImageObserver.SOMEBITS, x, y, w, h); 636 } 637 } 638 639 public BufferedImage getOpaqueRGBImage() { 640 if (bimage.getType() == BufferedImage.TYPE_INT_ARGB) { 641 int w = bimage.getWidth(); 642 int h = bimage.getHeight(); 643 int size = w * h; 644 645 // Note that we steal the data array here, but only for reading... 646 DataBufferInt db = (DataBufferInt)biRaster.getDataBuffer(); 647 int[] pixels = SunWritableRaster.stealData(db, 0); 648 649 for (int i = 0; i < size; i++) { 650 if ((pixels[i] >>> 24) != 0xff) { 651 return bimage; 652 } 653 } 654 655 ColorModel opModel = new DirectColorModel(24, 656 0x00ff0000, 657 0x0000ff00, 658 0x000000ff); 659 660 int bandmasks[] = {0x00ff0000, 0x0000ff00, 0x000000ff}; 661 WritableRaster opRaster = Raster.createPackedRaster(db, w, h, w, 662 bandmasks, 663 null); 664 665 try { 666 BufferedImage opImage = createImage(opModel, opRaster, 667 false, null); 668 return opImage; 669 } catch (Exception e) { 670 return bimage; 671 } 672 } 673 return bimage; 674 } 675 676 private boolean consuming = false; 677 678 public void imageComplete(int status) { 679 if (src != null) { 680 src.checkSecurity(null, false); 681 } 682 boolean done; 683 int info; 684 switch (status) { 685 default: 686 case ImageConsumer.IMAGEABORTED: 687 done = true; 688 info = ImageObserver.ABORT; 689 break; 690 case ImageConsumer.IMAGEERROR: 691 image.addInfo(ImageObserver.ERROR); 692 done = true; 693 info = ImageObserver.ERROR; 694 dispose(); 695 break; 696 case ImageConsumer.STATICIMAGEDONE: 697 done = true; 698 info = ImageObserver.ALLBITS; 699 break; 700 case ImageConsumer.SINGLEFRAMEDONE: 701 done = false; 702 info = ImageObserver.FRAMEBITS; 703 break; 704 } 705 synchronized (this) { 706 if (done) { 707 image.getSource().removeConsumer(this); 708 consuming = false; 709 newbits = null; 710 711 if (bimage != null) { 712 bimage = getOpaqueRGBImage(); 713 } 714 } 715 availinfo |= info; 716 notifyAll(); 717 } 718 719 newInfo(image, info, 0, 0, width, height); 720 721 image.infoDone(status); 722 } 723 724 /*synchronized*/ void startProduction() { 725 if (!consuming) { 726 consuming = true; 727 image.getSource().startProduction(this); 728 } 729 } 730 731 private int numWaiters; 732 733 private synchronized void checkConsumption() { 734 if (isWatcherListEmpty() && numWaiters == 0 && 735 ((availinfo & ImageObserver.ALLBITS) == 0)) 736 { 737 dispose(); 738 } 739 } 740 741 public synchronized void notifyWatcherListEmpty() { 742 checkConsumption(); 743 } 744 745 private synchronized void decrementWaiters() { 746 --numWaiters; 747 checkConsumption(); 748 } 749 750 public boolean prepare(ImageObserver iw) { 751 if (src != null) { 752 src.checkSecurity(null, false); 753 } 754 if ((availinfo & ImageObserver.ERROR) != 0) { 755 if (iw != null) { 756 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, 757 -1, -1, -1, -1); 758 } 759 return false; 760 } 761 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); 762 if (!done) { 763 addWatcher(iw); 764 startProduction(); 765 // Some producers deliver image data synchronously 766 done = ((availinfo & ImageObserver.ALLBITS) != 0); 767 } 768 return done; 769 } 770 771 public int check(ImageObserver iw) { 772 773 if (src != null) { 774 src.checkSecurity(null, false); 775 } 776 if ((availinfo & (ImageObserver.ERROR | ImageObserver.ALLBITS)) == 0) { 777 addWatcher(iw); 778 } 779 780 return availinfo; 781 } 782 783 public boolean drawToBufImage(Graphics g, ToolkitImage img, 784 int x, int y, Color bg, 785 ImageObserver iw) { 786 787 if (src != null) { 788 src.checkSecurity(null, false); 789 } 790 if ((availinfo & ImageObserver.ERROR) != 0) { 791 if (iw != null) { 792 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, 793 -1, -1, -1, -1); 794 } 795 return false; 796 } 797 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); 798 boolean abort = ((availinfo & ImageObserver.ABORT) != 0); 799 800 if (!done && !abort) { 801 addWatcher(iw); 802 startProduction(); 803 // Some producers deliver image data synchronously 804 done = ((availinfo & ImageObserver.ALLBITS) != 0); 805 } 806 807 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { 808 g.drawImage (bimage, x, y, bg, null); 809 } 810 811 return done; 812 } 813 814 public boolean drawToBufImage(Graphics g, ToolkitImage img, 815 int x, int y, int w, int h, 816 Color bg, ImageObserver iw) { 817 818 if (src != null) { 819 src.checkSecurity(null, false); 820 } 821 if ((availinfo & ImageObserver.ERROR) != 0) { 822 if (iw != null) { 823 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, 824 -1, -1, -1, -1); 825 } 826 return false; 827 } 828 829 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); 830 boolean abort = ((availinfo & ImageObserver.ABORT) != 0); 831 832 if (!done && !abort) { 833 addWatcher(iw); 834 startProduction(); 835 // Some producers deliver image data synchronously 836 done = ((availinfo & ImageObserver.ALLBITS) != 0); 837 } 838 839 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { 840 g.drawImage (bimage, x, y, w, h, bg, null); 841 } 842 843 return done; 844 } 845 846 public boolean drawToBufImage(Graphics g, ToolkitImage img, 847 int dx1, int dy1, int dx2, int dy2, 848 int sx1, int sy1, int sx2, int sy2, 849 Color bg, ImageObserver iw) { 850 851 if (src != null) { 852 src.checkSecurity(null, false); 853 } 854 if ((availinfo & ImageObserver.ERROR) != 0) { 855 if (iw != null) { 856 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, 857 -1, -1, -1, -1); 858 } 859 return false; 860 } 861 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); 862 boolean abort = ((availinfo & ImageObserver.ABORT) != 0); 863 864 if (!done && !abort) { 865 addWatcher(iw); 866 startProduction(); 867 // Some producers deliver image data synchronously 868 done = ((availinfo & ImageObserver.ALLBITS) != 0); 869 } 870 871 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { 872 g.drawImage (bimage, 873 dx1, dy1, dx2, dy2, 874 sx1, sy1, sx2, sy2, 875 bg, null); 876 } 877 878 return done; 879 } 880 881 public boolean drawToBufImage(Graphics g, ToolkitImage img, 882 AffineTransform xform, 883 ImageObserver iw) 884 { 885 Graphics2D g2 = (Graphics2D) g; 886 887 if (src != null) { 888 src.checkSecurity(null, false); 889 } 890 if ((availinfo & ImageObserver.ERROR) != 0) { 891 if (iw != null) { 892 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, 893 -1, -1, -1, -1); 894 } 895 return false; 896 } 897 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); 898 boolean abort = ((availinfo & ImageObserver.ABORT) != 0); 899 900 if (!done && !abort) { 901 addWatcher(iw); 902 startProduction(); 903 // Some producers deliver image data synchronously 904 done = ((availinfo & ImageObserver.ALLBITS) != 0); 905 } 906 907 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { 908 g2.drawImage (bimage, xform, null); 909 } 910 911 return done; 912 } 913 914 synchronized void abort() { 915 image.getSource().removeConsumer(this); 916 consuming = false; 917 newbits = null; 918 bimage = null; 919 biRaster = null; 920 cmodel = null; 921 srcLUT = null; 922 isDefaultBI = false; 923 isSameCM = false; 924 925 newInfo(image, ImageObserver.ABORT, -1, -1, -1, -1); 926 availinfo &= ~(ImageObserver.SOMEBITS 927 | ImageObserver.FRAMEBITS 928 | ImageObserver.ALLBITS 929 | ImageObserver.ERROR); 930 } 931 932 synchronized void dispose() { 933 image.getSource().removeConsumer(this); 934 consuming = false; 935 newbits = null; 936 availinfo &= ~(ImageObserver.SOMEBITS 937 | ImageObserver.FRAMEBITS 938 | ImageObserver.ALLBITS); 939 } 940 941 public void setAccelerationPriority(float priority) { 942 if (bimage != null) { 943 bimage.setAccelerationPriority(priority); 944 } 945 } 946 }