/* * 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 */ package com.google.code.appengine.awt.image; import java.util.Hashtable; import java.util.Vector; import org.apache.harmony.awt.internal.nls.Messages; import com.google.code.appengine.awt.image.ColorModel; import com.google.code.appengine.awt.image.ImageConsumer; import com.google.code.appengine.awt.image.ImageProducer; public class MemoryImageSource implements ImageProducer { int width; int height; ColorModel cm; byte bData[]; int iData[]; int offset; int scanline; Hashtable<?, ?> properties; Vector<ImageConsumer> consumers; boolean animated; boolean fullbuffers; int dataType; static final int DATA_TYPE_BYTE = 0; static final int DATA_TYPE_INT = 1; public MemoryImageSource(int w, int h, ColorModel cm, int pix[], int off, int scan, Hashtable<?, ?> props) { init(w, h, cm, pix, off, scan, props); } public MemoryImageSource(int w, int h, ColorModel cm, byte pix[], int off, int scan, Hashtable<?, ?> props) { init(w, h, cm, pix, off, scan, props); } public MemoryImageSource(int w, int h, int pix[], int off, int scan, Hashtable<?, ?> props) { init(w, h, ColorModel.getRGBdefault(), pix, off, scan, props); } public MemoryImageSource(int w, int h, ColorModel cm, int pix[], int off, int scan) { init(w, h, cm, pix, off, scan, null); } public MemoryImageSource(int w, int h, ColorModel cm, byte pix[], int off, int scan) { init(w, h, cm, pix, off, scan, null); } public MemoryImageSource(int w, int h, int pix[], int off, int scan) { init(w, h, ColorModel.getRGBdefault(), pix, off, scan, null); } public synchronized boolean isConsumer(ImageConsumer ic) { return consumers.contains(ic); } public void startProduction(ImageConsumer ic) { if(!isConsumer(ic) && ic != null) { consumers.addElement(ic); } try{ setHeader(ic); setPixels(ic, 0, 0, width, height); if(animated){ ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE); }else{ ic.imageComplete(ImageConsumer.STATICIMAGEDONE); if(isConsumer(ic)) { removeConsumer(ic); } } }catch(Exception e){ if(isConsumer(ic)) { ic.imageComplete(ImageConsumer.IMAGEERROR); } if(isConsumer(ic)) { removeConsumer(ic); } } } public void requestTopDownLeftRightResend(ImageConsumer ic) { } public synchronized void removeConsumer(ImageConsumer ic) { consumers.removeElement(ic); } public synchronized void addConsumer(ImageConsumer ic) { if(ic == null || consumers.contains(ic)) { return; } consumers.addElement(ic); } public synchronized void newPixels(int newpix[], ColorModel newmodel, int offset, int scansize) { this.dataType = DATA_TYPE_INT; this.iData = newpix; this.cm = newmodel; this.offset = offset; this.scanline = scansize; newPixels(); } public synchronized void newPixels(byte newpix[], ColorModel newmodel, int offset, int scansize) { this.dataType = DATA_TYPE_BYTE; this.bData = newpix; this.cm = newmodel; this.offset = offset; this.scanline = scansize; newPixels(); } public synchronized void setFullBufferUpdates(boolean fullbuffers) { if(this.fullbuffers == fullbuffers) { return; } this.fullbuffers = fullbuffers; if(animated){ Object consAr[] = consumers.toArray(); for (Object element : consAr) { ImageConsumer con = (ImageConsumer)element; try{ if(fullbuffers){ con.setHints(ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES); }else{ con.setHints(ImageConsumer.RANDOMPIXELORDER); } }catch(Exception e){ if(isConsumer(con)) { con.imageComplete(ImageConsumer.IMAGEERROR); } if(isConsumer(con)) { removeConsumer(con); } } } } } public synchronized void setAnimated(boolean animated) { if(this.animated == animated) { return; } Object consAr[] = consumers.toArray(); for (Object element : consAr) { ImageConsumer con = (ImageConsumer)element; try{ con.imageComplete(ImageConsumer.STATICIMAGEDONE); }catch(Exception e){ if(isConsumer(con)) { con.imageComplete(ImageConsumer.IMAGEERROR); } } if(isConsumer(con)){ removeConsumer(con); } } this.animated = animated; } public synchronized void newPixels(int x, int y, int w, int h, boolean framenotify) { if(animated){ if(fullbuffers){ x = 0; y = 0; w = width; h = height; }else{ if(x < 0){ w += x; x = 0; } if(w > width) { w = width - x; } if(y < 0){ h += y; y = 0; } } if(h > height) { h = height - y; } Object consAr[] = consumers.toArray(); for (Object element : consAr) { ImageConsumer con = (ImageConsumer)element; try{ if(w > 0 && h > 0) { setPixels(con, x, y, w, h); } if(framenotify) { con.imageComplete(ImageConsumer.SINGLEFRAMEDONE); } }catch(Exception ex){ if(isConsumer(con)) { con.imageComplete(ImageConsumer.IMAGEERROR); } if(isConsumer(con)) { removeConsumer(con); } } } } } public synchronized void newPixels(int x, int y, int w, int h) { newPixels(x, y, w, h, true); } public void newPixels() { newPixels(0, 0, width, height, true); } private void init(int width, int height, ColorModel model, byte pixels[], int off, int scan, Hashtable<?, ?> prop){ this.width = width; this.height = height; this.cm = model; this.bData = pixels; this.offset = off; this.scanline = scan; this.properties = prop; this.dataType = DATA_TYPE_BYTE; this.consumers = new Vector<ImageConsumer>(); } private void init(int width, int height, ColorModel model, int pixels[], int off, int scan, Hashtable<?, ?> prop){ this.width = width; this.height = height; this.cm = model; this.iData = pixels; this.offset = off; this.scanline = scan; this.properties = prop; this.dataType = DATA_TYPE_INT; this.consumers = new Vector<ImageConsumer>(); } private void setPixels(ImageConsumer con, int x, int y, int w, int h){ int pixelOff = scanline * y + offset + x; switch(dataType){ case DATA_TYPE_BYTE: con.setPixels(x, y, w, h, cm, bData, pixelOff, scanline); break; case DATA_TYPE_INT: con.setPixels(x, y, w, h, cm, iData, pixelOff, scanline); break; default: // awt.22A=Wrong type of pixels array throw new IllegalArgumentException(Messages.getString("awt.22A")); //$NON-NLS-1$ } } private synchronized void setHeader(ImageConsumer con){ con.setDimensions(width, height); con.setProperties(properties); con.setColorModel(cm); con.setHints(animated ? (fullbuffers ? (ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES) : ImageConsumer.RANDOMPIXELORDER) : (ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME)); } }