blob: ca9260b5a8c55c575a8d4b2558054b71bbe1a33f [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.awt.image;
27
28import java.awt.Color;
29import java.awt.Graphics;
30import java.awt.Transparency;
31import java.awt.AWTException;
32import java.awt.Rectangle;
33import java.awt.image.BufferedImage;
34import java.awt.image.ColorModel;
35import java.awt.image.DirectColorModel;
36import java.awt.image.IndexColorModel;
37import java.awt.image.ImageConsumer;
38import java.awt.image.ImageObserver;
39import sun.awt.image.ByteComponentRaster;
40import sun.awt.image.IntegerComponentRaster;
41import java.awt.image.Raster;
42import java.awt.image.WritableRaster;
43import java.awt.image.DataBuffer;
44import java.awt.image.DataBufferInt;
45import java.awt.Graphics2D;
46import java.awt.geom.AffineTransform;
47import sun.awt.image.ImageWatched;
48import java.util.Hashtable;
49
50public 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 public native void setICMpixels(int x, int y, int w, int h, int[] lut,
337 byte[] pix, int off, int scansize,
338 IntegerComponentRaster ict);
339
340 public native void setBytePixels(int x, int y, int w, int h, byte[] pix,
341 int off, int scansize,
342 ByteComponentRaster bct, int chanOff);
343 public native int setDiffICM(int x, int y, int w, int h, int[] lut,
344 int transPix, int numLut, IndexColorModel icm,
345 byte[] pix, int off, int scansize,
346 ByteComponentRaster bct, int chanOff);
347 static boolean s_useNative = true;
348
349 public void setPixels(int x, int y, int w, int h,
350 ColorModel model,
351 byte pix[], int off, int scansize) {
352 int lineOff=off;
353 int poff;
354 int[] newLUT=null;
355
356 if (src != null) {
357 src.checkSecurity(null, false);
358 }
359
360 // REMIND: What if the model doesn't fit in default color model?
361 synchronized (this) {
362 if (bimage == null) {
363 if (cmodel == null) {
364 cmodel = model;
365 }
366 createBufferedImage();
367 }
368 if (isSameCM && (cmodel != model) && (srcLUT != null) &&
369 (model instanceof IndexColorModel) &&
370 (biRaster instanceof ByteComponentRaster))
371 {
372 IndexColorModel icm = (IndexColorModel) model;
373 ByteComponentRaster bct = (ByteComponentRaster) biRaster;
374 int numlut = numSrcLUT;
375 if (setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,
376 numSrcLUT, icm,
377 pix, off, scansize, bct,
378 bct.getDataOffset(0)) == 0) {
379 convertToRGB();
380 }
381 else {
382 // Note that setDiffICM modified the raster directly
383 // so we must mark it as changed
384 bct.markDirty();
385 if (numlut != numSrcLUT) {
386 boolean hasAlpha = icm.hasAlpha();
387 if (srcLUTtransIndex != -1) {
388 hasAlpha = true;
389 }
390 int nbits = icm.getPixelSize();
391 icm = new IndexColorModel(nbits,
392 numSrcLUT, srcLUT,
393 0, hasAlpha,
394 srcLUTtransIndex,
395 (nbits > 8
396 ? DataBuffer.TYPE_USHORT
397 : DataBuffer.TYPE_BYTE));
398 cmodel = icm;
399 bimage = createImage(icm, bct, false, null);
400 }
401 return;
402 }
403 }
404
405 if (isDefaultBI) {
406 int pixel;
407 IntegerComponentRaster iraster =
408 (IntegerComponentRaster) biRaster;
409 if (srcLUT != null && model instanceof IndexColorModel) {
410 if (model != srcModel) {
411 // Fill in the new lut
412 ((IndexColorModel)model).getRGBs(srcLUT);
413 srcModel = model;
414 }
415
416 if (s_useNative) {
417 // Note that setICMpixels modifies the raster directly
418 // so we must mark it as changed afterwards
419 setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,
420 iraster);
421 iraster.markDirty();
422 }
423 else {
424 int[] storage = new int[w*h];
425 int soff = 0;
426 // It is an IndexColorModel
427 for (int yoff=0; yoff < h; yoff++,
428 lineOff += scansize) {
429 poff = lineOff;
430 for (int i=0; i < w; i++) {
431 storage[soff++] = srcLUT[pix[poff++]&0xff];
432 }
433 }
434 iraster.setDataElements(x, y, w, h, storage);
435 }
436 }
437 else {
438 int[] storage = new int[w];
439 for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
440 poff = lineOff;
441 for (int i=0; i < w; i++) {
442 storage[i] = model.getRGB(pix[poff++]&0xff);
443 }
444 iraster.setDataElements(x, yoff, w, 1, storage);
445 }
446 availinfo |= ImageObserver.SOMEBITS;
447 }
448 }
449 else if ((cmodel == model) &&
450 (biRaster instanceof ByteComponentRaster) &&
451 (biRaster.getNumDataElements() == 1)){
452 ByteComponentRaster bt = (ByteComponentRaster) biRaster;
453 if (w*h > 200) {
454 if (off == 0 && scansize == w) {
455 bt.putByteData(x, y, w, h, pix);
456 }
457 else {
458 byte[] bpix = new byte[w];
459 poff = off;
460 for (int yoff=y; yoff < y+h; yoff++) {
461 System.arraycopy(pix, poff, bpix, 0, w);
462 bt.putByteData(x, yoff, w, 1, bpix);
463 poff += scansize;
464 }
465 }
466 }
467 else {
468 // Only is faster if #pixels
469 // Note that setBytePixels modifies the raster directly
470 // so we must mark it as changed afterwards
471 setBytePixels(x, y, w, h, pix, off, scansize, bt,
472 bt.getDataOffset(0));
473 bt.markDirty();
474 }
475 }
476 else {
477 for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
478 poff = lineOff;
479 for (int xoff=x; xoff < x+w; xoff++) {
480 bimage.setRGB(xoff, yoff,
481 model.getRGB(pix[poff++]&0xff));
482 }
483 }
484 availinfo |= ImageObserver.SOMEBITS;
485 }
486 }
487
488 if ((availinfo & ImageObserver.FRAMEBITS) == 0) {
489 newInfo(image, ImageObserver.SOMEBITS, x, y, w, h);
490 }
491 }
492
493
494 public void setPixels(int x, int y, int w, int h, ColorModel model,
495 int pix[], int off, int scansize)
496 {
497 int lineOff=off;
498 int poff;
499
500 if (src != null) {
501 src.checkSecurity(null, false);
502 }
503
504 // REMIND: What if the model doesn't fit in default color model?
505 synchronized (this) {
506 if (bimage == null) {
507 if (cmodel == null) {
508 cmodel = model;
509 }
510 createBufferedImage();
511 }
512
513 int[] storage = new int[w];
514 int yoff;
515 int pixel;
516
517 if (cmodel instanceof IndexColorModel) {
518 // REMIND: Right now we don't support writing back into ICM
519 // images.
520 convertToRGB();
521 }
522
523 if ((model == cmodel) &&
524 (biRaster instanceof IntegerComponentRaster)) {
525 IntegerComponentRaster iraster =
526 (IntegerComponentRaster) biRaster;
527
528 if (off == 0 && scansize == w) {
529 iraster.setDataElements(x, y, w, h, pix);
530 }
531 else {
532 // Need to pack the data
533 for (yoff=y; yoff < y+h; yoff++, lineOff+=scansize) {
534 System.arraycopy(pix, lineOff, storage, 0, w);
535 iraster.setDataElements(x, yoff, w, 1, storage);
536 }
537 }
538 }
539 else {
540 if (model.getTransparency() != model.OPAQUE &&
541 cmodel.getTransparency() == cmodel.OPAQUE) {
542 convertToRGB();
543 }
544
545 if (isDefaultBI) {
546 IntegerComponentRaster iraster =
547 (IntegerComponentRaster) biRaster;
548 int[] data = iraster.getDataStorage();
549 if (cmodel.equals(model)) {
550 int sstride = iraster.getScanlineStride();
551 int doff = y*sstride + x;
552 for (yoff=0; yoff < h; yoff++, lineOff += scansize) {
553 System.arraycopy(pix, lineOff, data, doff, w);
554 doff += sstride;
555 }
556 // Note: manual modification of pixels, mark the
557 // raster as changed
558 iraster.markDirty();
559 }
560 else {
561 for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
562 poff = lineOff;
563 for (int i=0; i < w; i++) {
564 storage[i]=model.getRGB(pix[poff++]);
565 }
566 iraster.setDataElements(x, yoff, w, 1, storage);
567 }
568 }
569
570 availinfo |= ImageObserver.SOMEBITS;
571 }
572 else {
573 Object tmp = null;
574
575 for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) {
576 poff = lineOff;
577 for (int xoff=x; xoff < x+w; xoff++) {
578 pixel = model.getRGB(pix[poff++]);
579 tmp = cmodel.getDataElements(pixel,tmp);
580 biRaster.setDataElements(xoff, yoff,tmp);
581 }
582 }
583 availinfo |= ImageObserver.SOMEBITS;
584 }
585 }
586 }
587
588 // Can't do this here since we might need to transform/clip
589 // the region
590 if (((availinfo & ImageObserver.FRAMEBITS) == 0)) {
591 newInfo(image, ImageObserver.SOMEBITS, x, y, w, h);
592 }
593 }
594
595 public BufferedImage getOpaqueRGBImage() {
596 if (bimage.getType() == BufferedImage.TYPE_INT_ARGB) {
597 int w = bimage.getWidth();
598 int h = bimage.getHeight();
599 int size = w * h;
600
601 // Note that we steal the data array here, but only for reading...
602 DataBufferInt db = (DataBufferInt)biRaster.getDataBuffer();
603 int[] pixels = SunWritableRaster.stealData(db, 0);
604
605 for (int i = 0; i < size; i++) {
606 if ((pixels[i] >>> 24) != 0xff) {
607 return bimage;
608 }
609 }
610
611 ColorModel opModel = new DirectColorModel(24,
612 0x00ff0000,
613 0x0000ff00,
614 0x000000ff);
615
616 int bandmasks[] = {0x00ff0000, 0x0000ff00, 0x000000ff};
617 WritableRaster opRaster = Raster.createPackedRaster(db, w, h, w,
618 bandmasks,
619 null);
620
621 try {
622 BufferedImage opImage = createImage(opModel, opRaster,
623 false, null);
624 return opImage;
625 } catch (Exception e) {
626 return bimage;
627 }
628 }
629 return bimage;
630 }
631
632 private boolean consuming = false;
633
634 public void imageComplete(int status) {
635 if (src != null) {
636 src.checkSecurity(null, false);
637 }
638 boolean done;
639 int info;
640 switch (status) {
641 default:
642 case ImageConsumer.IMAGEABORTED:
643 done = true;
644 info = ImageObserver.ABORT;
645 break;
646 case ImageConsumer.IMAGEERROR:
647 image.addInfo(ImageObserver.ERROR);
648 done = true;
649 info = ImageObserver.ERROR;
650 dispose();
651 break;
652 case ImageConsumer.STATICIMAGEDONE:
653 done = true;
654 info = ImageObserver.ALLBITS;
655 break;
656 case ImageConsumer.SINGLEFRAMEDONE:
657 done = false;
658 info = ImageObserver.FRAMEBITS;
659 break;
660 }
661 synchronized (this) {
662 if (done) {
663 image.getSource().removeConsumer(this);
664 consuming = false;
665 newbits = null;
666
667 if (bimage != null) {
668 bimage = getOpaqueRGBImage();
669 }
670 }
671 availinfo |= info;
672 notifyAll();
673 }
674
675 newInfo(image, info, 0, 0, width, height);
676
677 image.infoDone(status);
678 }
679
680 /*synchronized*/ void startProduction() {
681 if (!consuming) {
682 consuming = true;
683 image.getSource().startProduction(this);
684 }
685 }
686
687 private int numWaiters;
688
689 private synchronized void checkConsumption() {
690 if (isWatcherListEmpty() && numWaiters == 0 &&
691 ((availinfo & ImageObserver.ALLBITS) == 0))
692 {
693 dispose();
694 }
695 }
696
697 public synchronized void notifyWatcherListEmpty() {
698 checkConsumption();
699 }
700
701 private synchronized void decrementWaiters() {
702 --numWaiters;
703 checkConsumption();
704 }
705
706 public boolean prepare(ImageObserver iw) {
707 if (src != null) {
708 src.checkSecurity(null, false);
709 }
710 if ((availinfo & ImageObserver.ERROR) != 0) {
711 if (iw != null) {
712 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
713 -1, -1, -1, -1);
714 }
715 return false;
716 }
717 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
718 if (!done) {
719 addWatcher(iw);
720 startProduction();
721 // Some producers deliver image data synchronously
722 done = ((availinfo & ImageObserver.ALLBITS) != 0);
723 }
724 return done;
725 }
726
727 public int check(ImageObserver iw) {
728
729 if (src != null) {
730 src.checkSecurity(null, false);
731 }
732 if ((availinfo & (ImageObserver.ERROR | ImageObserver.ALLBITS)) == 0) {
733 addWatcher(iw);
734 }
735
736 return availinfo;
737 }
738
739 public boolean drawToBufImage(Graphics g, ToolkitImage img,
740 int x, int y, Color bg,
741 ImageObserver iw) {
742
743 if (src != null) {
744 src.checkSecurity(null, false);
745 }
746 if ((availinfo & ImageObserver.ERROR) != 0) {
747 if (iw != null) {
748 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
749 -1, -1, -1, -1);
750 }
751 return false;
752 }
753 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
754 boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
755
756 if (!done && !abort) {
757 addWatcher(iw);
758 startProduction();
759 // Some producers deliver image data synchronously
760 done = ((availinfo & ImageObserver.ALLBITS) != 0);
761 }
762
763 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
764 g.drawImage (bimage, x, y, bg, null);
765 }
766
767 return done;
768 }
769
770 public boolean drawToBufImage(Graphics g, ToolkitImage img,
771 int x, int y, int w, int h,
772 Color bg, ImageObserver iw) {
773
774 if (src != null) {
775 src.checkSecurity(null, false);
776 }
777 if ((availinfo & ImageObserver.ERROR) != 0) {
778 if (iw != null) {
779 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
780 -1, -1, -1, -1);
781 }
782 return false;
783 }
784
785 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
786 boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
787
788 if (!done && !abort) {
789 addWatcher(iw);
790 startProduction();
791 // Some producers deliver image data synchronously
792 done = ((availinfo & ImageObserver.ALLBITS) != 0);
793 }
794
795 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
796 g.drawImage (bimage, x, y, w, h, bg, null);
797 }
798
799 return done;
800 }
801
802 public boolean drawToBufImage(Graphics g, ToolkitImage img,
803 int dx1, int dy1, int dx2, int dy2,
804 int sx1, int sy1, int sx2, int sy2,
805 Color bg, ImageObserver iw) {
806
807 if (src != null) {
808 src.checkSecurity(null, false);
809 }
810 if ((availinfo & ImageObserver.ERROR) != 0) {
811 if (iw != null) {
812 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
813 -1, -1, -1, -1);
814 }
815 return false;
816 }
817 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
818 boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
819
820 if (!done && !abort) {
821 addWatcher(iw);
822 startProduction();
823 // Some producers deliver image data synchronously
824 done = ((availinfo & ImageObserver.ALLBITS) != 0);
825 }
826
827 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
828 g.drawImage (bimage,
829 dx1, dy1, dx2, dy2,
830 sx1, sy1, sx2, sy2,
831 bg, null);
832 }
833
834 return done;
835 }
836
837 public boolean drawToBufImage(Graphics g, ToolkitImage img,
838 AffineTransform xform,
839 ImageObserver iw)
840 {
841 Graphics2D g2 = (Graphics2D) g;
842
843 if (src != null) {
844 src.checkSecurity(null, false);
845 }
846 if ((availinfo & ImageObserver.ERROR) != 0) {
847 if (iw != null) {
848 iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT,
849 -1, -1, -1, -1);
850 }
851 return false;
852 }
853 boolean done = ((availinfo & ImageObserver.ALLBITS) != 0);
854 boolean abort = ((availinfo & ImageObserver.ABORT) != 0);
855
856 if (!done && !abort) {
857 addWatcher(iw);
858 startProduction();
859 // Some producers deliver image data synchronously
860 done = ((availinfo & ImageObserver.ALLBITS) != 0);
861 }
862
863 if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) {
864 g2.drawImage (bimage, xform, null);
865 }
866
867 return done;
868 }
869
870 synchronized void abort() {
871 image.getSource().removeConsumer(this);
872 consuming = false;
873 newbits = null;
874 bimage = null;
875 biRaster = null;
876 cmodel = null;
877 srcLUT = null;
878 isDefaultBI = false;
879 isSameCM = false;
880
881 newInfo(image, ImageObserver.ABORT, -1, -1, -1, -1);
882 availinfo &= ~(ImageObserver.SOMEBITS
883 | ImageObserver.FRAMEBITS
884 | ImageObserver.ALLBITS
885 | ImageObserver.ERROR);
886 }
887
888 synchronized void dispose() {
889 image.getSource().removeConsumer(this);
890 consuming = false;
891 newbits = null;
892 availinfo &= ~(ImageObserver.SOMEBITS
893 | ImageObserver.FRAMEBITS
894 | ImageObserver.ALLBITS);
895 }
896
897 public void setAccelerationPriority(float priority) {
898 if (bimage != null) {
899 bimage.setAccelerationPriority(priority);
900 }
901 }
902}