diff options
Diffstat (limited to 'awt/java/awt/image/MemoryImageSource.java')
-rw-r--r-- | awt/java/awt/image/MemoryImageSource.java | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/awt/java/awt/image/MemoryImageSource.java b/awt/java/awt/image/MemoryImageSource.java new file mode 100644 index 0000000..644fd40 --- /dev/null +++ b/awt/java/awt/image/MemoryImageSource.java @@ -0,0 +1,603 @@ +/* + * 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$ + */ + +package java.awt.image; + +import java.util.Hashtable; +import java.util.Vector; + +import org.apache.harmony.awt.internal.nls.Messages; + +/** + * The MemoryImageSource class is used to produces pixels of an image from an + * array. This class can manage a memory image which contains an animation or + * custom rendering. + * + * @since Android 1.0 + */ +public class MemoryImageSource implements ImageProducer { + + /** + * The width. + */ + int width; + + /** + * The height. + */ + int height; + + /** + * The cm. + */ + ColorModel cm; + + /** + * The b data. + */ + byte bData[]; + + /** + * The i data. + */ + int iData[]; + + /** + * The offset. + */ + int offset; + + /** + * The scanline. + */ + int scanline; + + /** + * The properties. + */ + Hashtable<?, ?> properties; + + /** + * The consumers. + */ + Vector<ImageConsumer> consumers; + + /** + * The animated. + */ + boolean animated; + + /** + * The fullbuffers. + */ + boolean fullbuffers; + + /** + * The data type. + */ + int dataType; + + /** + * The Constant DATA_TYPE_BYTE. + */ + static final int DATA_TYPE_BYTE = 0; + + /** + * The Constant DATA_TYPE_INT. + */ + static final int DATA_TYPE_INT = 1; + + /** + * Instantiates a new MemoryImageSource with the specified parameters. + * + * @param w + * the width of the rectangular area of pixels. + * @param h + * the height of the rectangular area of pixels. + * @param cm + * the specified ColorModel. + * @param pix + * the pixel array. + * @param off + * the offset in the pixel array. + * @param scan + * the distance from one pixel's row to the next in the pixel + * array. + * @param props + * the set of properties to be used for image processing. + */ + public MemoryImageSource(int w, int h, ColorModel cm, int pix[], int off, int scan, + Hashtable<?, ?> props) { + init(w, h, cm, pix, off, scan, props); + } + + /** + * Instantiates a new MemoryImageSource with the specified parameters. + * + * @param w + * the width of the rectangular area of pixels. + * @param h + * the height of the rectangular area of pixels. + * @param cm + * the specified ColorModel. + * @param pix + * the pixel array. + * @param off + * the offset in the pixel array. + * @param scan + * the distance from one pixel's row to the next in the pixel + * array. + * @param props + * the set of properties to be used for image processing. + */ + public MemoryImageSource(int w, int h, ColorModel cm, byte pix[], int off, int scan, + Hashtable<?, ?> props) { + init(w, h, cm, pix, off, scan, props); + } + + /** + * Instantiates a new MemoryImageSource with the specified parameters and + * default RGB ColorModel. + * + * @param w + * the width of the rectangular area of pixels. + * @param h + * the height of the rectangular area of pixels. + * @param pix + * the pixel array. + * @param off + * the offset in the pixel array. + * @param scan + * the distance from one pixel's row to the next in the pixel + * array. + * @param props + * the set of properties to be used for image processing. + */ + public MemoryImageSource(int w, int h, int pix[], int off, int scan, Hashtable<?, ?> props) { + init(w, h, ColorModel.getRGBdefault(), pix, off, scan, props); + } + + /** + * Instantiates a new MemoryImageSource with the specified parameters. + * + * @param w + * the width of the rectangular area of pixels. + * @param h + * the height of the rectangular area of pixels. + * @param cm + * the specified ColorModel. + * @param pix + * the pixel array. + * @param off + * the offset in the pixel array. + * @param scan + * the distance from one pixel's row to the next in the pixel + * array. + */ + public MemoryImageSource(int w, int h, ColorModel cm, int pix[], int off, int scan) { + init(w, h, cm, pix, off, scan, null); + } + + /** + * Instantiates a new MemoryImageSource with the specified parameters. + * + * @param w + * the width of the rectangular area of pixels. + * @param h + * the height of the rectangular area of pixels. + * @param cm + * the specified ColorModel. + * @param pix + * the pixel array. + * @param off + * the offset in the pixel array. + * @param scan + * the distance from one pixel's row to the next in the pixel + * array. + */ + public MemoryImageSource(int w, int h, ColorModel cm, byte pix[], int off, int scan) { + init(w, h, cm, pix, off, scan, null); + } + + /** + * Instantiates a new MemoryImageSource with the specified parameters and + * default RGB ColorModel. + * + * @param w + * the width of the rectangular area of pixels. + * @param h + * the height of the rectangular area of pixels. + * @param pix + * the pixels array. + * @param off + * the offset in the pixel array. + * @param scan + * the distance from one pixel's row to the next in the pixel + * array. + */ + 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); + } + + /** + * Replaces the pixel data with a new pixel array for holding the pixels for + * this image. If an animation flag is set to true value by the + * setAnimated() method, the new pixels will be immediately delivered to the + * ImageConsumers. + * + * @param newpix + * the new pixel array. + * @param newmodel + * the new ColorModel. + * @param offset + * the offset in the array. + * @param scansize + * the distance from one row of pixels to the next row in the + * pixel array. + */ + 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(); + } + + /** + * Replaces the pixel data with a new pixel array for holding the pixels for + * this image. If an animation flag is set to true value by the + * setAnimated() method, the new pixels will be immediately delivered to the + * ImageConsumers. + * + * @param newpix + * the new pixel array. + * @param newmodel + * the new ColorModel. + * @param offset + * the offset in the array. + * @param scansize + * the distance from one row of pixels to the next row in the + * pixel array. + */ + 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(); + } + + /** + * Sets the full buffer updates flag to true. If this is an animated image, + * the image consumers hints are updated accordingly. + * + * @param fullbuffers + * the true if the pixel buffer should be sent always. + */ + 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); + } + } + } + } + } + + /** + * Sets the flag that tells whether this memory image has more than one + * frame (for animation): true for multiple frames, false if this class + * represents a single frame image. + * + * @param animated + * whether this image represents an animation. + */ + 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; + } + + /** + * Sends the specified rectangular area of the buffer to ImageConsumers and + * notifies them that an animation frame is completed only if the {@code + * framenotify} parameter is true. That works only if the animated flag has + * been set to true by the setAnimated() method. If the full buffer update + * flag has been set to true by the setFullBufferUpdates() method, then the + * entire buffer will always be sent ignoring parameters. + * + * @param x + * the X coordinate of the rectangular area. + * @param y + * the Y coordinate of the rectangular area. + * @param w + * the width of the rectangular area. + * @param h + * the height of the rectangular area. + * @param framenotify + * true if a SINGLEFRAMEDONE notification should be sent to the + * registered consumers, false otherwise. + */ + 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); + } + } + } + } + } + + /** + * Sends the specified rectangular area of the buffer to the ImageConsumers + * and notifies them that an animation frame is completed if the animated + * flag has been set to true by the setAnimated() method. If the full buffer + * update flag has been set to true by the setFullBufferUpdates() method, + * then the entire buffer will always be sent ignoring parameters. + * + * @param x + * the X coordinate of the rectangular area. + * @param y + * the Y coordinate of the rectangular area. + * @param w + * the width of the rectangular area. + * @param h + * the height of the rectangular area. + */ + public synchronized void newPixels(int x, int y, int w, int h) { + newPixels(x, y, w, h, true); + } + + /** + * Sends a new buffer of pixels to the ImageConsumers and notifies them that + * an animation frame is completed if the animated flag has been set to true + * by the setAnimated() method. + */ + public void newPixels() { + newPixels(0, 0, width, height, true); + } + + /** + * Inits the. + * + * @param width + * the width. + * @param height + * the height. + * @param model + * the model. + * @param pixels + * the pixels. + * @param off + * the off. + * @param scan + * the scan. + * @param prop + * the prop. + */ + 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>(); + + } + + /** + * Inits the. + * + * @param width + * the width. + * @param height + * the height. + * @param model + * the model. + * @param pixels + * the pixels. + * @param off + * the off. + * @param scan + * the scan. + * @param prop + * the prop. + */ + 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>(); + } + + /** + * Sets the pixels. + * + * @param con + * the con. + * @param x + * the x. + * @param y + * the y. + * @param w + * the w. + * @param h + * the h. + */ + 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$ + } + } + + /** + * Sets the header. + * + * @param con + * the new header. + */ + 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)); + } + +} |