summaryrefslogtreecommitdiffstats
path: root/awt/org/apache/harmony/awt/gl/image/OffscreenImage.java
diff options
context:
space:
mode:
Diffstat (limited to 'awt/org/apache/harmony/awt/gl/image/OffscreenImage.java')
-rw-r--r--awt/org/apache/harmony/awt/gl/image/OffscreenImage.java532
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;
+ }
+}