diff options
Diffstat (limited to 'awt/org/apache/harmony/awt/gl/image/OffscreenImage.java')
-rw-r--r-- | awt/org/apache/harmony/awt/gl/image/OffscreenImage.java | 532 |
1 files changed, 532 insertions, 0 deletions
diff --git a/awt/org/apache/harmony/awt/gl/image/OffscreenImage.java b/awt/org/apache/harmony/awt/gl/image/OffscreenImage.java new file mode 100644 index 0000000..3445f8e --- /dev/null +++ b/awt/org/apache/harmony/awt/gl/image/OffscreenImage.java @@ -0,0 +1,532 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @author Igor V. Stolyarov + * @version $Revision$ + */ +/* + * Created on 22.12.2004 + * + */ +package org.apache.harmony.awt.gl.image; + +import java.awt.Graphics; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DirectColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.image.IndexColorModel; +import java.awt.image.WritableRaster; +import java.util.Hashtable; +import java.util.Vector; + +import org.apache.harmony.awt.gl.ImageSurface; +import org.apache.harmony.awt.internal.nls.Messages; + + +/** + * This class represent implementation of abstract Image class + */ +public class OffscreenImage extends Image implements ImageConsumer { + + static final ColorModel rgbCM = ColorModel.getRGBdefault(); + ImageProducer src; + BufferedImage image; + ColorModel cm; + WritableRaster raster; + boolean isIntRGB; + Hashtable<?, ?> properties; + Vector<ImageObserver> observers; + int width; + int height; + int imageState; + int hints; + private boolean producing; + private ImageSurface imageSurf; + + public OffscreenImage(ImageProducer ip){ + imageState = 0; + src = ip; + width = -1; + height = -1; + observers = new Vector<ImageObserver>(); + producing = false; + } + + @Override + public Object getProperty(String name, ImageObserver observer) { + if(name == null) { + // awt.38=Property name is not defined + throw new NullPointerException(Messages.getString("awt.38")); //$NON-NLS-1$ + } + if(properties == null){ + addObserver(observer); + startProduction(); + if(properties == null) { + return null; + } + } + Object prop = properties.get(name); + if(prop == null) { + prop = UndefinedProperty; + } + return prop; + } + + @Override + public ImageProducer getSource() { + return src; + } + + @Override + public int getWidth(ImageObserver observer) { + if((imageState & ImageObserver.WIDTH) == 0){ + addObserver(observer); + startProduction(); + if((imageState & ImageObserver.WIDTH) == 0) { + return -1; + } + } + return width; + } + + @Override + public int getHeight(ImageObserver observer) { + if((imageState & ImageObserver.HEIGHT) == 0){ + addObserver(observer); + startProduction(); + if((imageState & ImageObserver.HEIGHT) == 0) { + return -1; + } + } + return height; + } + + @Override + public Graphics getGraphics() { + // awt.39=This method is not implemented for image obtained from ImageProducer + throw new UnsupportedOperationException(Messages.getString("awt.39")); //$NON-NLS-1$ + } + + @Override + public void flush() { + stopProduction(); + imageUpdate(this, ImageObserver.ABORT, -1, -1, -1, -1); + imageState &= ~ImageObserver.ERROR; + imageState = 0; + image = null; + cm = null; + raster = null; + hints = 0; + width = -1; + height = -1; + } + + public void setProperties(Hashtable<?, ?> properties) { + this.properties = properties; + imageUpdate(this, ImageObserver.PROPERTIES, 0, 0, width, height); + } + + public void setColorModel(ColorModel cm) { + this.cm = cm; + } + + /* + * We suppose what in case loading JPEG image then image has DirectColorModel + * and for infill image Raster will use setPixels method with int array. + * + * In case loading GIF image, for raster infill, is used setPixels method with + * byte array and Color Model is IndexColorModel. But Color Model may + * be changed during this process. Then is called setPixels method with + * int array and image force to default color model - int ARGB. The rest + * pixels are sending in DirectColorModel. + */ + public void setPixels(int x, int y, int w, int h, ColorModel model, + int[] pixels, int off, int scansize) { + if(raster == null){ + if(cm == null){ + if(model == null) { + // awt.3A=Color Model is null + throw new NullPointerException(Messages.getString("awt.3A")); //$NON-NLS-1$ + } + cm = model; + } + createRaster(); + } + + if(model == null) { + model = cm; + } + if(cm != model){ + forceToIntARGB(); + } + + if(cm == model && model.getTransferType() == DataBuffer.TYPE_INT && + raster.getNumDataElements() == 1){ + + DataBufferInt dbi = (DataBufferInt) raster.getDataBuffer(); + int data[] = dbi.getData(); + int scanline = raster.getWidth(); + int rof = dbi.getOffset() + y * scanline + x; + for(int lineOff = off, line = y; line < y + h; + line++, lineOff += scansize, rof += scanline){ + + System.arraycopy(pixels, lineOff, data, rof, w); + } + + }else if(isIntRGB){ + int buff[] = new int[w]; + DataBufferInt dbi = (DataBufferInt) raster.getDataBuffer(); + int data[] = dbi.getData(); + int scanline = raster.getWidth(); + int rof = dbi.getOffset() + y * scanline + x; + for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize, + rof += scanline) { + + for (int sx = x, idx = 0; sx < x + w; sx++, idx++) { + buff[idx] = model.getRGB(pixels[sOff + idx]); + } + System.arraycopy(buff, 0, data, rof, w); + } + }else{ + Object buf = null; + for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize) { + for (int sx = x, idx = 0; sx < x + w; sx++, idx++) { + int rgb = model.getRGB(pixels[sOff + idx]); + buf = cm.getDataElements(rgb, buf); + raster.setDataElements(sx, sy, buf); + } + } + } + + if (imageSurf != null) { + imageSurf.invalidate(); + } + + imageUpdate(this, ImageObserver.SOMEBITS, 0, 0, width, height); + } + + public void setPixels(int x, int y, int w, int h, ColorModel model, + byte[] pixels, int off, int scansize) { + + if(raster == null){ + if(cm == null){ + if(model == null) { + // awt.3A=Color Model is null + throw new NullPointerException(Messages.getString("awt.3A")); //$NON-NLS-1$ + } + cm = model; + } + createRaster(); + } + if(model == null) { + model = cm; + } + if(model != cm){ + forceToIntARGB(); + } + + if(isIntRGB){ + int buff[] = new int[w]; + IndexColorModel icm = (IndexColorModel) model; + int colorMap[] = new int[icm.getMapSize()]; + icm.getRGBs(colorMap); + DataBufferInt dbi = (DataBufferInt) raster.getDataBuffer(); + int data[] = dbi.getData(); + int scanline = raster.getWidth(); + int rof = dbi.getOffset() + y * scanline + x; + if(model instanceof IndexColorModel){ + + for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize, + rof += scanline) { + for (int sx = x, idx = 0; sx < x + w; sx++, idx++) { + buff[idx] = colorMap[pixels[sOff + idx] & 0xff]; + } + System.arraycopy(buff, 0, data, rof, w); + } + }else{ + + for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize, + rof += scanline) { + for (int sx = x, idx = 0; sx < x + w; sx++, idx++) { + buff[idx] = model.getRGB(pixels[sOff + idx] & 0xff); + } + System.arraycopy(buff, 0, data, rof, w); + } + } + }else if(model == cm && model.getTransferType() == DataBuffer.TYPE_BYTE && + raster.getNumDataElements() == 1){ + + DataBufferByte dbb = (DataBufferByte)raster.getDataBuffer(); + byte data[] = dbb.getData(); + int scanline = raster.getWidth(); + int rof = dbb.getOffset() + y * scanline + x; + for(int lineOff = off, line = y; line < y + h; + line++, lineOff += scansize, rof += scanline){ + System.arraycopy(pixels, lineOff, data, rof, w); + } + // BEGIN android-added (taken from newer Harmony) + }else if(model == cm && model.getTransferType() == DataBuffer.TYPE_BYTE && + cm instanceof ComponentColorModel){ + + int nc = cm.getNumComponents(); + byte stride[] = new byte[scansize]; + for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize) { + System.arraycopy(pixels, sOff, stride, 0, scansize); + + raster.setDataElements(x, sy, w, 1, stride); + } + // END android-added + }else { + for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize) { + for (int sx = x, idx = 0; sx < x + w; sx++, idx++) { + int rgb = model.getRGB(pixels[sOff + idx] & 0xff); + raster.setDataElements(sx, sy, cm.getDataElements(rgb, null)); + } + } + } + + if (imageSurf != null) { + imageSurf.invalidate(); + } + + imageUpdate(this, ImageObserver.SOMEBITS, 0, 0, width, height); + } + + public void setDimensions(int width, int height) { + if(width <= 0 || height <= 0){ + imageComplete(ImageObserver.ERROR); + return; + } + + this.width = width; + this.height = height; + imageUpdate(this, (ImageObserver.HEIGHT | ImageObserver.WIDTH), + 0, 0, width, height); + } + + public void setHints(int hints) { + this.hints = hints; + } + + public void imageComplete(int state) { + int flag; + switch(state){ + case IMAGEABORTED: + flag = ImageObserver.ABORT; + break; + case IMAGEERROR: + flag = ImageObserver.ERROR | ImageObserver.ABORT; + break; + case SINGLEFRAMEDONE: + flag = ImageObserver.FRAMEBITS; + break; + case STATICIMAGEDONE: + flag = ImageObserver.ALLBITS; + break; + default: + // awt.3B=Incorrect ImageConsumer completion status + throw new IllegalArgumentException(Messages.getString("awt.3B")); //$NON-NLS-1$ + } + imageUpdate(this, flag, 0, 0, width, height); + + if((flag & (ImageObserver.ERROR | ImageObserver.ABORT | + ImageObserver.ALLBITS)) != 0 ) { + stopProduction(); + observers.removeAllElements(); + } + } + + public /*synchronized*/ BufferedImage getBufferedImage(){ + if(image == null){ + ColorModel model = getColorModel(); + WritableRaster wr = getRaster(); + if(model != null && wr != null) { + image = new BufferedImage(model, wr, model.isAlphaPremultiplied(), null); + } + } + return image; + } + + public /*synchronized*/ int checkImage(ImageObserver observer){ + addObserver(observer); + return imageState; + } + + public /*synchronized*/ boolean prepareImage(ImageObserver observer){ + if((imageState & ImageObserver.ERROR) != 0){ + if(observer != null){ + observer.imageUpdate(this, ImageObserver.ERROR | + ImageObserver.ABORT, -1, -1, -1, -1); + } + return false; + } + if((imageState & ImageObserver.ALLBITS) != 0) { + return true; + } + addObserver(observer); + startProduction(); + return ((imageState & ImageObserver.ALLBITS) != 0); + } + + public /*synchronized*/ ColorModel getColorModel(){ + if(cm == null) { + startProduction(); + } + return cm; + } + + public /*synchronized*/ WritableRaster getRaster(){ + if(raster == null) { + startProduction(); + } + return raster; + } + + public int getState(){ + return imageState; + } + + private /*synchronized*/ void addObserver(ImageObserver observer){ + if(observer != null){ + if(observers.contains(observer)) { + return; + } + if((imageState & ImageObserver.ERROR) != 0){ + observer.imageUpdate(this, ImageObserver.ERROR | + ImageObserver.ABORT, -1, -1, -1, -1); + return; + } + if((imageState & ImageObserver.ALLBITS) != 0){ + observer.imageUpdate(this, imageState, 0, 0, width, height); + return; + } + observers.addElement(observer); + } + } + + private synchronized void startProduction(){ + if(!producing){ + imageState &= ~ImageObserver.ABORT; + producing = true; + src.startProduction(this); + } + } + + private synchronized void stopProduction(){ + producing = false; + src.removeConsumer(this); + } + + private void createRaster(){ + try{ + raster = cm.createCompatibleWritableRaster(width, height); + isIntRGB = false; + if(cm instanceof DirectColorModel){ + DirectColorModel dcm = (DirectColorModel) cm; + if(dcm.getTransferType() == DataBuffer.TYPE_INT && + dcm.getRedMask() == 0xff0000 && + dcm.getGreenMask() == 0xff00 && + dcm.getBlueMask() == 0xff){ + isIntRGB = true; + } + } + }catch(Exception e){ + cm = ColorModel.getRGBdefault(); + raster = cm.createCompatibleWritableRaster(width, height); + isIntRGB = true; + } + } + + private /*synchronized*/ void imageUpdate(Image img, int infoflags, int x, int y, + int width, int height){ + + imageState |= infoflags; + for (ImageObserver observer : observers) { + observer.imageUpdate(this, infoflags, x, y, width, height); + } + +// notifyAll(); + } + + private void forceToIntARGB(){ + + int w = raster.getWidth(); + int h = raster.getHeight(); + + WritableRaster destRaster = rgbCM.createCompatibleWritableRaster(w, h); + + Object obj = null; + int pixels[] = new int[w]; + + if(cm instanceof IndexColorModel){ + IndexColorModel icm = (IndexColorModel) cm; + int colorMap[] = new int[icm.getMapSize()]; + icm.getRGBs(colorMap); + + for (int y = 0; y < h; y++) { + obj = raster.getDataElements(0, y, w, 1, obj); + byte ba[] = (byte[]) obj; + for (int x = 0; x < ba.length; x++) { + pixels[x] = colorMap[ba[x] & 0xff]; + } + destRaster.setDataElements(0, y, w, 1, pixels); + } + + }else{ + for(int y = 0; y < h; y++){ + for(int x = 0; x < w; x++){ + obj = raster.getDataElements(x, y, obj); + pixels[x] = cm.getRGB(obj); + } + destRaster.setDataElements(0, y, w, 1, pixels); + } + } + + synchronized(this){ + if(imageSurf != null){ + imageSurf.dispose(); + imageSurf = null; + } + if(image != null){ + image.flush(); + image = null; + } + cm = rgbCM; + raster = destRaster; + isIntRGB = true; + } + } + + public ImageSurface getImageSurface() { + if (imageSurf == null) { + ColorModel model = getColorModel(); + WritableRaster wr = getRaster(); + if(model != null && wr != null) { + imageSurf = new ImageSurface(model, wr); + } + } + return imageSurf; + } +} |