| /* | |
| * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package sun.awt.image; | |
| import java.awt.Color; | |
| import java.awt.Graphics; | |
| import java.awt.Graphics2D; | |
| import java.awt.Rectangle; | |
| import java.awt.Transparency; | |
| import java.awt.geom.AffineTransform; | |
| import java.awt.image.BufferedImage; | |
| import java.awt.image.ColorModel; | |
| import java.awt.image.DataBuffer; | |
| import java.awt.image.DataBufferInt; | |
| import java.awt.image.DirectColorModel; | |
| import java.awt.image.ImageConsumer; | |
| import java.awt.image.ImageObserver; | |
| import java.awt.image.IndexColorModel; | |
| import java.awt.image.Raster; | |
| import java.awt.image.WritableRaster; | |
| import java.util.Hashtable; | |
| public class ImageRepresentation extends ImageWatched implements ImageConsumer | |
| { | |
| InputStreamImageSource src; | |
| ToolkitImage image; | |
| int tag; | |
| long pData; // used by windows native code only -- internal state REMIND ATTN @@ | |
| int width = -1; | |
| int height = -1; | |
| int hints; | |
| int availinfo; | |
| Rectangle newbits; | |
| BufferedImage bimage; | |
| WritableRaster biRaster; | |
| protected ColorModel cmodel; | |
| ColorModel srcModel = null; | |
| int[] srcLUT = null; | |
| int srcLUTtransIndex = -1; | |
| int numSrcLUT = 0; | |
| boolean forceCMhint; | |
| int sstride; | |
| boolean isDefaultBI = false; | |
| boolean isSameCM = false; | |
| private static native void initIDs(); | |
| static { | |
| /* ensure that the necessary native libraries are loaded */ | |
| NativeLibLoader.loadLibraries(); | |
| initIDs(); | |
| } | |
| /** | |
| * Create an ImageRepresentation for the given Image. The | |
| * width and height are unknown at this point. The color | |
| * model is a hint as to the color model to use when creating | |
| * the buffered image. If null, the src color model will | |
| * be used. | |
| */ | |
| public ImageRepresentation(ToolkitImage im, ColorModel cmodel, boolean | |
| forceCMhint) { | |
| image = im; | |
| if (image.getSource() instanceof InputStreamImageSource) { | |
| src = (InputStreamImageSource) image.getSource(); | |
| } | |
| setColorModel(cmodel); | |
| this.forceCMhint = forceCMhint; | |
| } | |
| /* REMIND: Only used for Frame.setIcon - should use ImageWatcher instead */ | |
| public synchronized void reconstruct(int flags) { | |
| int missinginfo = flags & ~availinfo; | |
| if ((availinfo & ImageObserver.ERROR) == 0 && missinginfo != 0) { | |
| numWaiters++; | |
| try { | |
| startProduction(); | |
| missinginfo = flags & ~availinfo; | |
| while ((availinfo & (ImageObserver.ERROR | ImageObserver.FRAMEBITS)) == 0 | |
| && missinginfo != 0) | |
| { | |
| try { | |
| wait(); | |
| } catch (InterruptedException e) { | |
| Thread.currentThread().interrupt(); | |
| return; | |
| } | |
| missinginfo = flags & ~availinfo; | |
| } | |
| } finally { | |
| decrementWaiters(); | |
| } | |
| } | |
| } | |
| public void setDimensions(int w, int h) { | |
| image.setDimensions(w, h); | |
| newInfo(image, (ImageObserver.WIDTH | ImageObserver.HEIGHT), | |
| 0, 0, w, h); | |
| if (w <= 0 || h <= 0) { | |
| imageComplete(ImageConsumer.IMAGEERROR); | |
| return; | |
| } | |
| if (width != w || height != h) { | |
| // dimension mismatch => trigger recreation of the buffer | |
| bimage = null; | |
| } | |
| width = w; | |
| height = h; | |
| availinfo |= ImageObserver.WIDTH | ImageObserver.HEIGHT; | |
| } | |
| public int getWidth() { | |
| return width; | |
| } | |
| public int getHeight() { | |
| return height; | |
| } | |
| ColorModel getColorModel() { | |
| return cmodel; | |
| } | |
| BufferedImage getBufferedImage() { | |
| return bimage; | |
| } | |
| /** | |
| * Returns the BufferedImage that will be used as the representation of | |
| * the pixel data. Subclasses can override this method to return | |
| * platform specific subclasses of BufferedImage that may or may not be | |
| * accelerated. | |
| * | |
| * It is subclass' responsibility to propagate acceleration priority | |
| * to the newly created image. | |
| */ | |
| protected BufferedImage createImage(ColorModel cm, | |
| WritableRaster raster, | |
| boolean isRasterPremultiplied, | |
| Hashtable<?,?> properties) | |
| { | |
| BufferedImage bi = | |
| new BufferedImage(cm, raster, isRasterPremultiplied, null); | |
| bi.setAccelerationPriority(image.getAccelerationPriority()); | |
| return bi; | |
| } | |
| public void setProperties(Hashtable<?,?> props) { | |
| image.setProperties(props); | |
| newInfo(image, ImageObserver.PROPERTIES, 0, 0, 0, 0); | |
| } | |
| public void setColorModel(ColorModel model) { | |
| srcModel = model; | |
| // Check to see if model is INT_RGB | |
| if (model instanceof IndexColorModel) { | |
| if (model.getTransparency() == Transparency.TRANSLUCENT) { | |
| // REMIND: | |
| // Probably need to composite anyway so force ARGB | |
| cmodel = ColorModel.getRGBdefault(); | |
| srcLUT = null; | |
| } | |
| else { | |
| IndexColorModel icm = (IndexColorModel) model; | |
| numSrcLUT = icm.getMapSize(); | |
| srcLUT = new int[Math.max(numSrcLUT, 256)]; | |
| icm.getRGBs(srcLUT); | |
| srcLUTtransIndex = icm.getTransparentPixel(); | |
| cmodel = model; | |
| } | |
| } | |
| else { | |
| if (cmodel == null) { | |
| cmodel = model; | |
| srcLUT = null; | |
| } | |
| else if (model instanceof DirectColorModel) { | |
| // If it is INT_RGB or INT_ARGB, use the model | |
| DirectColorModel dcm = (DirectColorModel) model; | |
| if ((dcm.getRedMask() == 0xff0000) && | |
| (dcm.getGreenMask() == 0xff00) && | |
| (dcm.getBlueMask() == 0x00ff)) { | |
| cmodel = model; | |
| srcLUT = null; | |
| } | |
| } | |
| } | |
| isSameCM = (cmodel == model); | |
| } | |
| void createBufferedImage() { | |
| // REMIND: Be careful! Is this called every time there is a | |
| // startProduction? We only want to call it if it is new or | |
| // there is an error | |
| isDefaultBI = false; | |
| try { | |
| biRaster = cmodel.createCompatibleWritableRaster(width, height); | |
| bimage = createImage(cmodel, biRaster, | |
| cmodel.isAlphaPremultiplied(), null); | |
| } catch (Exception e) { | |
| // Create a default image | |
| cmodel = ColorModel.getRGBdefault(); | |
| biRaster = cmodel.createCompatibleWritableRaster(width, height); | |
| bimage = createImage(cmodel, biRaster, false, null); | |
| } | |
| int type = bimage.getType(); | |
| if ((cmodel == ColorModel.getRGBdefault()) || | |
| (type == BufferedImage.TYPE_INT_RGB) || | |
| (type == BufferedImage.TYPE_INT_ARGB_PRE)) { | |
| isDefaultBI = true; | |
| } | |
| else if (cmodel instanceof DirectColorModel) { | |
| DirectColorModel dcm = (DirectColorModel) cmodel; | |
| if (dcm.getRedMask() == 0xff0000 && | |
| dcm.getGreenMask() == 0xff00 && | |
| dcm.getBlueMask() == 0xff) { | |
| isDefaultBI = true; | |
| } | |
| } | |
| } | |
| private void convertToRGB() { | |
| int w = bimage.getWidth(); | |
| int h = bimage.getHeight(); | |
| int size = w*h; | |
| DataBufferInt dbi = new DataBufferInt(size); | |
| // Note that stealData() requires a markDirty() afterwards | |
| // since we modify the data in it. | |
| int[] newpixels = SunWritableRaster.stealData(dbi, 0); | |
| if (cmodel instanceof IndexColorModel && | |
| biRaster instanceof ByteComponentRaster && | |
| biRaster.getNumDataElements() == 1) | |
| { | |
| ByteComponentRaster bct = (ByteComponentRaster) biRaster; | |
| byte[] data = bct.getDataStorage(); | |
| int coff = bct.getDataOffset(0); | |
| for (int i=0; i < size; i++) { | |
| newpixels[i] = srcLUT[data[coff+i]&0xff]; | |
| } | |
| } | |
| else { | |
| Object srcpixels = null; | |
| int off=0; | |
| for (int y=0; y < h; y++) { | |
| for (int x=0; x < w; x++) { | |
| srcpixels=biRaster.getDataElements(x, y, srcpixels); | |
| newpixels[off++] = cmodel.getRGB(srcpixels); | |
| } | |
| } | |
| } | |
| // We modified the data array directly above so mark it as dirty now... | |
| SunWritableRaster.markDirty(dbi); | |
| isSameCM = false; | |
| cmodel = ColorModel.getRGBdefault(); | |
| int[] bandMasks = {0x00ff0000, | |
| 0x0000ff00, | |
| 0x000000ff, | |
| 0xff000000}; | |
| biRaster = Raster.createPackedRaster(dbi,w,h,w, | |
| bandMasks,null); | |
| bimage = createImage(cmodel, biRaster, | |
| cmodel.isAlphaPremultiplied(), null); | |
| srcLUT = null; | |
| isDefaultBI = true; | |
| } | |
| public void setHints(int h) { | |
| hints = h; | |
| } | |
| private native boolean setICMpixels(int x, int y, int w, int h, int[] lut, | |
| byte[] pix, int off, int scansize, | |
| IntegerComponentRaster ict); | |
| private native boolean setDiffICM(int x, int y, int w, int h, int[] lut, | |
| int transPix, int numLut, IndexColorModel icm, | |
| byte[] pix, int off, int scansize, | |
| ByteComponentRaster bct, int chanOff); | |
| static boolean s_useNative = true; | |
| public void setPixels(int x, int y, int w, int h, | |
| ColorModel model, | |
| byte[] pix, int off, int scansize) { | |
| int lineOff=off; | |
| int poff; | |
| int[] newLUT=null; | |
| // REMIND: What if the model doesn't fit in default color model? | |
| synchronized (this) { | |
| if (bimage == null) { | |
| if (cmodel == null) { | |
| cmodel = model; | |
| } | |
| createBufferedImage(); | |
| } | |
| if (w <= 0 || h <= 0) { | |
| return; | |
| } | |
| int biWidth = biRaster.getWidth(); | |
| int biHeight = biRaster.getHeight(); | |
| int x1 = x+w; // Overflow protection below | |
| int y1 = y+h; // Overflow protection below | |
| if (x < 0) { | |
| off -= x; | |
| x = 0; | |
| } else if (x1 < 0) { | |
| x1 = biWidth; // Must be overflow | |
| } | |
| if (y < 0) { | |
| off -= y*scansize; | |
| y = 0; | |
| } else if (y1 < 0) { | |
| y1 = biHeight; // Must be overflow | |
| } | |
| if (x1 > biWidth) { | |
| x1 = biWidth; | |
| } | |
| if (y1 > biHeight) { | |
| y1 = biHeight; | |
| } | |
| if (x >= x1 || y >= y1) { | |
| return; | |
| } | |
| // x,y,x1,y1 are all >= 0, so w,h must be >= 0 | |
| w = x1-x; | |
| h = y1-y; | |
| // off is first pixel read so it must be in bounds | |
| if (off < 0 || off >= pix.length) { | |
| // They overflowed their own array | |
| throw new ArrayIndexOutOfBoundsException("Data offset out of bounds."); | |
| } | |
| // pix.length and off are >= 0 so remainder >= 0 | |
| int remainder = pix.length - off; | |
| if (remainder < w) { | |
| // They overflowed their own array | |
| throw new ArrayIndexOutOfBoundsException("Data array is too short."); | |
| } | |
| int num; | |
| if (scansize < 0) { | |
| num = (off / -scansize) + 1; | |
| } else if (scansize > 0) { | |
| num = ((remainder-w) / scansize) + 1; | |
| } else { | |
| num = h; | |
| } | |
| if (h > num) { | |
| // They overflowed their own array. | |
| throw new ArrayIndexOutOfBoundsException("Data array is too short."); | |
| } | |
| if (isSameCM && (cmodel != model) && (srcLUT != null) && | |
| (model instanceof IndexColorModel) && | |
| (biRaster instanceof ByteComponentRaster)) | |
| { | |
| IndexColorModel icm = (IndexColorModel) model; | |
| ByteComponentRaster bct = (ByteComponentRaster) biRaster; | |
| int numlut = numSrcLUT; | |
| if (!setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex, | |
| numSrcLUT, icm, | |
| pix, off, scansize, bct, | |
| bct.getDataOffset(0))) { | |
| convertToRGB(); | |
| } | |
| else { | |
| // Note that setDiffICM modified the raster directly | |
| // so we must mark it as changed | |
| bct.markDirty(); | |
| if (numlut != numSrcLUT) { | |
| boolean hasAlpha = icm.hasAlpha(); | |
| if (srcLUTtransIndex != -1) { | |
| hasAlpha = true; | |
| } | |
| int nbits = icm.getPixelSize(); | |
| icm = new IndexColorModel(nbits, | |
| numSrcLUT, srcLUT, | |
| 0, hasAlpha, | |
| srcLUTtransIndex, | |
| (nbits > 8 | |
| ? DataBuffer.TYPE_USHORT | |
| : DataBuffer.TYPE_BYTE)); | |
| cmodel = icm; | |
| bimage = createImage(icm, bct, false, null); | |
| } | |
| return; | |
| } | |
| } | |
| if (isDefaultBI) { | |
| int pixel; | |
| IntegerComponentRaster iraster = | |
| (IntegerComponentRaster) biRaster; | |
| if (srcLUT != null && model instanceof IndexColorModel) { | |
| if (model != srcModel) { | |
| // Fill in the new lut | |
| ((IndexColorModel)model).getRGBs(srcLUT); | |
| srcModel = model; | |
| } | |
| if (s_useNative) { | |
| // Note that setICMpixels modifies the raster directly | |
| // so we must mark it as changed afterwards | |
| if (setICMpixels(x, y, w, h, srcLUT, pix, off, scansize, | |
| iraster)) | |
| { | |
| iraster.markDirty(); | |
| } else { | |
| abort(); | |
| return; | |
| } | |
| } | |
| else { | |
| int[] storage = new int[w*h]; | |
| int soff = 0; | |
| // It is an IndexColorModel | |
| for (int yoff=0; yoff < h; yoff++, | |
| lineOff += scansize) { | |
| poff = lineOff; | |
| for (int i=0; i < w; i++) { | |
| storage[soff++] = srcLUT[pix[poff++]&0xff]; | |
| } | |
| } | |
| iraster.setDataElements(x, y, w, h, storage); | |
| } | |
| } | |
| else { | |
| int[] storage = new int[w]; | |
| for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) { | |
| poff = lineOff; | |
| for (int i=0; i < w; i++) { | |
| storage[i] = model.getRGB(pix[poff++]&0xff); | |
| } | |
| iraster.setDataElements(x, yoff, w, 1, storage); | |
| } | |
| availinfo |= ImageObserver.SOMEBITS; | |
| } | |
| } | |
| else if ((cmodel == model) && | |
| (biRaster instanceof ByteComponentRaster) && | |
| (biRaster.getNumDataElements() == 1)){ | |
| ByteComponentRaster bt = (ByteComponentRaster) biRaster; | |
| if (off == 0 && scansize == w) { | |
| bt.putByteData(x, y, w, h, pix); | |
| } | |
| else { | |
| byte[] bpix = new byte[w]; | |
| poff = off; | |
| for (int yoff=y; yoff < y+h; yoff++) { | |
| System.arraycopy(pix, poff, bpix, 0, w); | |
| bt.putByteData(x, yoff, w, 1, bpix); | |
| poff += scansize; | |
| } | |
| } | |
| } | |
| else { | |
| for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) { | |
| poff = lineOff; | |
| for (int xoff=x; xoff < x+w; xoff++) { | |
| bimage.setRGB(xoff, yoff, | |
| model.getRGB(pix[poff++]&0xff)); | |
| } | |
| } | |
| availinfo |= ImageObserver.SOMEBITS; | |
| } | |
| } | |
| if ((availinfo & ImageObserver.FRAMEBITS) == 0) { | |
| newInfo(image, ImageObserver.SOMEBITS, x, y, w, h); | |
| } | |
| } | |
| public void setPixels(int x, int y, int w, int h, ColorModel model, | |
| int[] pix, int off, int scansize) | |
| { | |
| int lineOff=off; | |
| int poff; | |
| // REMIND: What if the model doesn't fit in default color model? | |
| synchronized (this) { | |
| if (bimage == null) { | |
| if (cmodel == null) { | |
| cmodel = model; | |
| } | |
| createBufferedImage(); | |
| } | |
| int[] storage = new int[w]; | |
| int yoff; | |
| int pixel; | |
| if (cmodel instanceof IndexColorModel) { | |
| // REMIND: Right now we don't support writing back into ICM | |
| // images. | |
| convertToRGB(); | |
| } | |
| if ((model == cmodel) && | |
| (biRaster instanceof IntegerComponentRaster)) { | |
| IntegerComponentRaster iraster = | |
| (IntegerComponentRaster) biRaster; | |
| if (off == 0 && scansize == w) { | |
| iraster.setDataElements(x, y, w, h, pix); | |
| } | |
| else { | |
| // Need to pack the data | |
| for (yoff=y; yoff < y+h; yoff++, lineOff+=scansize) { | |
| System.arraycopy(pix, lineOff, storage, 0, w); | |
| iraster.setDataElements(x, yoff, w, 1, storage); | |
| } | |
| } | |
| } | |
| else { | |
| if (model.getTransparency() != Transparency.OPAQUE && | |
| cmodel.getTransparency() == Transparency.OPAQUE) { | |
| convertToRGB(); | |
| } | |
| if (isDefaultBI) { | |
| IntegerComponentRaster iraster = | |
| (IntegerComponentRaster) biRaster; | |
| int[] data = iraster.getDataStorage(); | |
| if (cmodel.equals(model)) { | |
| int sstride = iraster.getScanlineStride(); | |
| int doff = y*sstride + x; | |
| for (yoff=0; yoff < h; yoff++, lineOff += scansize) { | |
| System.arraycopy(pix, lineOff, data, doff, w); | |
| doff += sstride; | |
| } | |
| // Note: manual modification of pixels, mark the | |
| // raster as changed | |
| iraster.markDirty(); | |
| } | |
| else { | |
| for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) { | |
| poff = lineOff; | |
| for (int i=0; i < w; i++) { | |
| storage[i]=model.getRGB(pix[poff++]); | |
| } | |
| iraster.setDataElements(x, yoff, w, 1, storage); | |
| } | |
| } | |
| availinfo |= ImageObserver.SOMEBITS; | |
| } | |
| else { | |
| Object tmp = null; | |
| for (yoff=y; yoff < y+h; yoff++, lineOff += scansize) { | |
| poff = lineOff; | |
| for (int xoff=x; xoff < x+w; xoff++) { | |
| pixel = model.getRGB(pix[poff++]); | |
| tmp = cmodel.getDataElements(pixel,tmp); | |
| biRaster.setDataElements(xoff, yoff,tmp); | |
| } | |
| } | |
| availinfo |= ImageObserver.SOMEBITS; | |
| } | |
| } | |
| } | |
| // Can't do this here since we might need to transform/clip | |
| // the region | |
| if (((availinfo & ImageObserver.FRAMEBITS) == 0)) { | |
| newInfo(image, ImageObserver.SOMEBITS, x, y, w, h); | |
| } | |
| } | |
| public BufferedImage getOpaqueRGBImage() { | |
| if (bimage.getType() == BufferedImage.TYPE_INT_ARGB) { | |
| int w = bimage.getWidth(); | |
| int h = bimage.getHeight(); | |
| int size = w * h; | |
| // Note that we steal the data array here, but only for reading... | |
| DataBufferInt db = (DataBufferInt)biRaster.getDataBuffer(); | |
| int[] pixels = SunWritableRaster.stealData(db, 0); | |
| for (int i = 0; i < size; i++) { | |
| if ((pixels[i] >>> 24) != 0xff) { | |
| return bimage; | |
| } | |
| } | |
| ColorModel opModel = new DirectColorModel(24, | |
| 0x00ff0000, | |
| 0x0000ff00, | |
| 0x000000ff); | |
| int[] bandmasks = {0x00ff0000, 0x0000ff00, 0x000000ff}; | |
| WritableRaster opRaster = Raster.createPackedRaster(db, w, h, w, | |
| bandmasks, | |
| null); | |
| try { | |
| BufferedImage opImage = createImage(opModel, opRaster, | |
| false, null); | |
| return opImage; | |
| } catch (Exception e) { | |
| return bimage; | |
| } | |
| } | |
| return bimage; | |
| } | |
| private boolean consuming = false; | |
| public void imageComplete(int status) { | |
| boolean done; | |
| int info; | |
| switch (status) { | |
| default: | |
| case ImageConsumer.IMAGEABORTED: | |
| done = true; | |
| info = ImageObserver.ABORT; | |
| break; | |
| case ImageConsumer.IMAGEERROR: | |
| image.addInfo(ImageObserver.ERROR); | |
| done = true; | |
| info = ImageObserver.ERROR; | |
| dispose(); | |
| break; | |
| case ImageConsumer.STATICIMAGEDONE: | |
| done = true; | |
| info = ImageObserver.ALLBITS; | |
| break; | |
| case ImageConsumer.SINGLEFRAMEDONE: | |
| done = false; | |
| info = ImageObserver.FRAMEBITS; | |
| break; | |
| } | |
| synchronized (this) { | |
| if (done) { | |
| image.getSource().removeConsumer(this); | |
| consuming = false; | |
| newbits = null; | |
| if (bimage != null) { | |
| bimage = getOpaqueRGBImage(); | |
| } | |
| } | |
| availinfo |= info; | |
| notifyAll(); | |
| } | |
| newInfo(image, info, 0, 0, width, height); | |
| image.infoDone(status); | |
| } | |
| /*synchronized*/ void startProduction() { | |
| if (!consuming) { | |
| consuming = true; | |
| image.getSource().startProduction(this); | |
| } | |
| } | |
| private int numWaiters; | |
| private synchronized void checkConsumption() { | |
| if (isWatcherListEmpty() && numWaiters == 0 && | |
| ((availinfo & ImageObserver.ALLBITS) == 0)) | |
| { | |
| dispose(); | |
| } | |
| } | |
| public synchronized void notifyWatcherListEmpty() { | |
| checkConsumption(); | |
| } | |
| private synchronized void decrementWaiters() { | |
| --numWaiters; | |
| checkConsumption(); | |
| } | |
| public boolean prepare(ImageObserver iw) { | |
| if ((availinfo & ImageObserver.ERROR) != 0) { | |
| if (iw != null) { | |
| iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, | |
| -1, -1, -1, -1); | |
| } | |
| return false; | |
| } | |
| boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| if (!done) { | |
| addWatcher(iw); | |
| startProduction(); | |
| // Some producers deliver image data synchronously | |
| done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| } | |
| return done; | |
| } | |
| public int check(ImageObserver iw) { | |
| if ((availinfo & (ImageObserver.ERROR | ImageObserver.ALLBITS)) == 0) { | |
| addWatcher(iw); | |
| } | |
| return availinfo; | |
| } | |
| public boolean drawToBufImage(Graphics g, ToolkitImage img, | |
| int x, int y, Color bg, | |
| ImageObserver iw) { | |
| if ((availinfo & ImageObserver.ERROR) != 0) { | |
| if (iw != null) { | |
| iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, | |
| -1, -1, -1, -1); | |
| } | |
| return false; | |
| } | |
| boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| boolean abort = ((availinfo & ImageObserver.ABORT) != 0); | |
| if (!done && !abort) { | |
| addWatcher(iw); | |
| startProduction(); | |
| // Some producers deliver image data synchronously | |
| done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| } | |
| if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { | |
| g.drawImage (bimage, x, y, bg, null); | |
| } | |
| return done; | |
| } | |
| public boolean drawToBufImage(Graphics g, ToolkitImage img, | |
| int x, int y, int w, int h, | |
| Color bg, ImageObserver iw) { | |
| if ((availinfo & ImageObserver.ERROR) != 0) { | |
| if (iw != null) { | |
| iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, | |
| -1, -1, -1, -1); | |
| } | |
| return false; | |
| } | |
| boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| boolean abort = ((availinfo & ImageObserver.ABORT) != 0); | |
| if (!done && !abort) { | |
| addWatcher(iw); | |
| startProduction(); | |
| // Some producers deliver image data synchronously | |
| done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| } | |
| if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { | |
| g.drawImage (bimage, x, y, w, h, bg, null); | |
| } | |
| return done; | |
| } | |
| public boolean drawToBufImage(Graphics g, ToolkitImage img, | |
| int dx1, int dy1, int dx2, int dy2, | |
| int sx1, int sy1, int sx2, int sy2, | |
| Color bg, ImageObserver iw) { | |
| if ((availinfo & ImageObserver.ERROR) != 0) { | |
| if (iw != null) { | |
| iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, | |
| -1, -1, -1, -1); | |
| } | |
| return false; | |
| } | |
| boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| boolean abort = ((availinfo & ImageObserver.ABORT) != 0); | |
| if (!done && !abort) { | |
| addWatcher(iw); | |
| startProduction(); | |
| // Some producers deliver image data synchronously | |
| done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| } | |
| if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { | |
| g.drawImage (bimage, | |
| dx1, dy1, dx2, dy2, | |
| sx1, sy1, sx2, sy2, | |
| bg, null); | |
| } | |
| return done; | |
| } | |
| public boolean drawToBufImage(Graphics g, ToolkitImage img, | |
| AffineTransform xform, | |
| ImageObserver iw) | |
| { | |
| Graphics2D g2 = (Graphics2D) g; | |
| if ((availinfo & ImageObserver.ERROR) != 0) { | |
| if (iw != null) { | |
| iw.imageUpdate(image, ImageObserver.ERROR|ImageObserver.ABORT, | |
| -1, -1, -1, -1); | |
| } | |
| return false; | |
| } | |
| boolean done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| boolean abort = ((availinfo & ImageObserver.ABORT) != 0); | |
| if (!done && !abort) { | |
| addWatcher(iw); | |
| startProduction(); | |
| // Some producers deliver image data synchronously | |
| done = ((availinfo & ImageObserver.ALLBITS) != 0); | |
| } | |
| if (done || (0 != (availinfo & ImageObserver.FRAMEBITS))) { | |
| g2.drawImage (bimage, xform, null); | |
| } | |
| return done; | |
| } | |
| synchronized void abort() { | |
| image.getSource().removeConsumer(this); | |
| consuming = false; | |
| newbits = null; | |
| bimage = null; | |
| biRaster = null; | |
| cmodel = null; | |
| srcLUT = null; | |
| isDefaultBI = false; | |
| isSameCM = false; | |
| newInfo(image, ImageObserver.ABORT, -1, -1, -1, -1); | |
| availinfo &= ~(ImageObserver.SOMEBITS | |
| | ImageObserver.FRAMEBITS | |
| | ImageObserver.ALLBITS | |
| | ImageObserver.ERROR); | |
| } | |
| synchronized void dispose() { | |
| image.getSource().removeConsumer(this); | |
| consuming = false; | |
| newbits = null; | |
| availinfo &= ~(ImageObserver.SOMEBITS | |
| | ImageObserver.FRAMEBITS | |
| | ImageObserver.ALLBITS); | |
| } | |
| public void setAccelerationPriority(float priority) { | |
| if (bimage != null) { | |
| bimage.setAccelerationPriority(priority); | |
| } | |
| } | |
| } |