/* * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ /* **************************************************************** ****************************************************************** ****************************************************************** *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** As an unpublished work pursuant to Title 17 of the United *** States Code. All rights reserved. ****************************************************************** ****************************************************************** ******************************************************************/ package java.awt.image; import sun.java2d.StateTrackable.State; import static sun.java2d.StateTrackable.State.*; import sun.java2d.StateTrackableDelegate; import sun.awt.image.SunWritableRaster; /** * This class exists to wrap one or more data arrays. Each data array in * the DataBuffer is referred to as a bank. Accessor methods for getting * and setting elements of the DataBuffer's banks exist with and without * a bank specifier. The methods without a bank specifier use the default 0th * bank. The DataBuffer can optionally take an offset per bank, so that * data in an existing array can be used even if the interesting data * doesn't start at array location zero. Getting or setting the 0th * element of a bank, uses the (0+offset)th element of the array. The * size field specifies how much of the data array is available for * use. Size + offset for a given bank should never be greater * than the length of the associated data array. The data type of * a data buffer indicates the type of the data array(s) and may also * indicate additional semantics, e.g. storing unsigned 8-bit data * in elements of a byte array. The data type may be TYPE_UNDEFINED * or one of the types defined below. Other types may be added in * the future. Generally, an object of class DataBuffer will be cast down * to one of its data type specific subclasses to access data type specific * methods for improved performance. Currently, the Java 2D(tm) API * image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT, * TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data. * @see java.awt.image.Raster * @see java.awt.image.SampleModel */ public abstract class DataBuffer { /** Tag for unsigned byte data. */ public static final int TYPE_BYTE = 0; /** Tag for unsigned short data. */ public static final int TYPE_USHORT = 1; /** Tag for signed short data. Placeholder for future use. */ public static final int TYPE_SHORT = 2; /** Tag for int data. */ public static final int TYPE_INT = 3; /** Tag for float data. Placeholder for future use. */ public static final int TYPE_FLOAT = 4; /** Tag for double data. Placeholder for future use. */ public static final int TYPE_DOUBLE = 5; /** Tag for undefined data. */ public static final int TYPE_UNDEFINED = 32; /** The data type of this DataBuffer. */ protected int dataType; /** The number of banks in this DataBuffer. */ protected int banks; /** Offset into default (first) bank from which to get the first element. */ protected int offset; /** Usable size of all banks. */ protected int size; /** Offsets into all banks. */ protected int offsets[]; /* The current StateTrackable state. */ StateTrackableDelegate theTrackable; /** Size of the data types indexed by DataType tags defined above. */ private static final int dataTypeSize[] = {8,16,16,32,32,64}; /** Returns the size (in bits) of the data type, given a datatype tag. * @param type the value of one of the defined datatype tags * @return the size of the data type * @throws IllegalArgumentException if <code>type</code> is less than * zero or greater than {@link #TYPE_DOUBLE} */ public static int getDataTypeSize(int type) { if (type < TYPE_BYTE || type > TYPE_DOUBLE) { throw new IllegalArgumentException("Unknown data type "+type); } return dataTypeSize[type]; } /** * Constructs a DataBuffer containing one bank of the specified * data type and size. * * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks */ protected DataBuffer(int dataType, int size) { this(UNTRACKABLE, dataType, size); } /** * Constructs a DataBuffer containing one bank of the specified * data type and size with the indicated initial {@link State State}. * * @param initialState the initial {@link State State} state of the data * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks * @since 1.7 */ DataBuffer(State initialState, int dataType, int size) { this.theTrackable = StateTrackableDelegate.createInstance(initialState); this.dataType = dataType; this.banks = 1; this.size = size; this.offset = 0; this.offsets = new int[1]; // init to 0 by new } /** * Constructs a DataBuffer containing the specified number of * banks. Each bank has the specified size and an offset of 0. * * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks * @param numBanks the number of banks in this * <code>DataBuffer</code> */ protected DataBuffer(int dataType, int size, int numBanks) { this(UNTRACKABLE, dataType, size, numBanks); } /** * Constructs a DataBuffer containing the specified number of * banks with the indicated initial {@link State State}. * Each bank has the specified size and an offset of 0. * * @param initialState the initial {@link State State} state of the data * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks * @param numBanks the number of banks in this * <code>DataBuffer</code> * @since 1.7 */ DataBuffer(State initialState, int dataType, int size, int numBanks) { this.theTrackable = StateTrackableDelegate.createInstance(initialState); this.dataType = dataType; this.banks = numBanks; this.size = size; this.offset = 0; this.offsets = new int[banks]; // init to 0 by new } /** * Constructs a DataBuffer that contains the specified number * of banks. Each bank has the specified datatype, size and offset. * * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks * @param numBanks the number of banks in this * <code>DataBuffer</code> * @param offset the offset for each bank */ protected DataBuffer(int dataType, int size, int numBanks, int offset) { this(UNTRACKABLE, dataType, size, numBanks, offset); } /** * Constructs a DataBuffer that contains the specified number * of banks with the indicated initial {@link State State}. * Each bank has the specified datatype, size and offset. * * @param initialState the initial {@link State State} state of the data * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks * @param numBanks the number of banks in this * <code>DataBuffer</code> * @param offset the offset for each bank * @since 1.7 */ DataBuffer(State initialState, int dataType, int size, int numBanks, int offset) { this.theTrackable = StateTrackableDelegate.createInstance(initialState); this.dataType = dataType; this.banks = numBanks; this.size = size; this.offset = offset; this.offsets = new int[numBanks]; for (int i = 0; i < numBanks; i++) { this.offsets[i] = offset; } } /** * Constructs a DataBuffer which contains the specified number * of banks. Each bank has the specified datatype and size. The * offset for each bank is specified by its respective entry in * the offsets array. * * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks * @param numBanks the number of banks in this * <code>DataBuffer</code> * @param offsets an array containing an offset for each bank. * @throws ArrayIndexOutOfBoundsException if <code>numBanks</code> * does not equal the length of <code>offsets</code> */ protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) { this(UNTRACKABLE, dataType, size, numBanks, offsets); } /** * Constructs a DataBuffer which contains the specified number * of banks with the indicated initial {@link State State}. * Each bank has the specified datatype and size. The * offset for each bank is specified by its respective entry in * the offsets array. * * @param initialState the initial {@link State State} state of the data * @param dataType the data type of this <code>DataBuffer</code> * @param size the size of the banks * @param numBanks the number of banks in this * <code>DataBuffer</code> * @param offsets an array containing an offset for each bank. * @throws ArrayIndexOutOfBoundsException if <code>numBanks</code> * does not equal the length of <code>offsets</code> * @since 1.7 */ DataBuffer(State initialState, int dataType, int size, int numBanks, int offsets[]) { if (numBanks != offsets.length) { throw new ArrayIndexOutOfBoundsException("Number of banks" + " does not match number of bank offsets"); } this.theTrackable = StateTrackableDelegate.createInstance(initialState); this.dataType = dataType; this.banks = numBanks; this.size = size; this.offset = offsets[0]; this.offsets = (int[])offsets.clone(); } /** Returns the data type of this DataBuffer. * @return the data type of this <code>DataBuffer</code>. */ public int getDataType() { return dataType; } /** Returns the size (in array elements) of all banks. * @return the size of all banks. */ public int getSize() { return size; } /** Returns the offset of the default bank in array elements. * @return the offset of the default bank. */ public int getOffset() { return offset; } /** Returns the offsets (in array elements) of all the banks. * @return the offsets of all banks. */ public int[] getOffsets() { return (int[])offsets.clone(); } /** Returns the number of banks in this DataBuffer. * @return the number of banks. */ public int getNumBanks() { return banks; } /** * Returns the requested data array element from the first (default) bank * as an integer. * @param i the index of the requested data array element * @return the data array element at the specified index. * @see #setElem(int, int) * @see #setElem(int, int, int) */ public int getElem(int i) { return getElem(0,i); } /** * Returns the requested data array element from the specified bank * as an integer. * @param bank the specified bank * @param i the index of the requested data array element * @return the data array element at the specified index from the * specified bank at the specified index. * @see #setElem(int, int) * @see #setElem(int, int, int) */ public abstract int getElem(int bank, int i); /** * Sets the requested data array element in the first (default) bank * from the given integer. * @param i the specified index into the data array * @param val the data to set the element at the specified index in * the data array * @see #getElem(int) * @see #getElem(int, int) */ public void setElem(int i, int val) { setElem(0,i,val); } /** * Sets the requested data array element in the specified bank * from the given integer. * @param bank the specified bank * @param i the specified index into the data array * @param val the data to set the element in the specified bank * at the specified index in the data array * @see #getElem(int) * @see #getElem(int, int) */ public abstract void setElem(int bank, int i, int val); /** * Returns the requested data array element from the first (default) bank * as a float. The implementation in this class is to cast getElem(i) * to a float. Subclasses may override this method if another * implementation is needed. * @param i the index of the requested data array element * @return a float value representing the data array element at the * specified index. * @see #setElemFloat(int, float) * @see #setElemFloat(int, int, float) */ public float getElemFloat(int i) { return (float)getElem(i); } /** * Returns the requested data array element from the specified bank * as a float. The implementation in this class is to cast * {@link #getElem(int, int)} * to a float. Subclasses can override this method if another * implementation is needed. * @param bank the specified bank * @param i the index of the requested data array element * @return a float value representing the data array element from the * specified bank at the specified index. * @see #setElemFloat(int, float) * @see #setElemFloat(int, int, float) */ public float getElemFloat(int bank, int i) { return (float)getElem(bank,i); } /** * Sets the requested data array element in the first (default) bank * from the given float. The implementation in this class is to cast * val to an int and call {@link #setElem(int, int)}. Subclasses * can override this method if another implementation is needed. * @param i the specified index * @param val the value to set the element at the specified index in * the data array * @see #getElemFloat(int) * @see #getElemFloat(int, int) */ public void setElemFloat(int i, float val) { setElem(i,(int)val); } /** * Sets the requested data array element in the specified bank * from the given float. The implementation in this class is to cast * val to an int and call {@link #setElem(int, int)}. Subclasses can * override this method if another implementation is needed. * @param bank the specified bank * @param i the specified index * @param val the value to set the element in the specified bank at * the specified index in the data array * @see #getElemFloat(int) * @see #getElemFloat(int, int) */ public void setElemFloat(int bank, int i, float val) { setElem(bank,i,(int)val); } /** * Returns the requested data array element from the first (default) bank * as a double. The implementation in this class is to cast * {@link #getElem(int)} * to a double. Subclasses can override this method if another * implementation is needed. * @param i the specified index * @return a double value representing the element at the specified * index in the data array. * @see #setElemDouble(int, double) * @see #setElemDouble(int, int, double) */ public double getElemDouble(int i) { return (double)getElem(i); } /** * Returns the requested data array element from the specified bank as * a double. The implementation in this class is to cast getElem(bank, i) * to a double. Subclasses may override this method if another * implementation is needed. * @param bank the specified bank * @param i the specified index * @return a double value representing the element from the specified * bank at the specified index in the data array. * @see #setElemDouble(int, double) * @see #setElemDouble(int, int, double) */ public double getElemDouble(int bank, int i) { return (double)getElem(bank,i); } /** * Sets the requested data array element in the first (default) bank * from the given double. The implementation in this class is to cast * val to an int and call {@link #setElem(int, int)}. Subclasses can * override this method if another implementation is needed. * @param i the specified index * @param val the value to set the element at the specified index * in the data array * @see #getElemDouble(int) * @see #getElemDouble(int, int) */ public void setElemDouble(int i, double val) { setElem(i,(int)val); } /** * Sets the requested data array element in the specified bank * from the given double. The implementation in this class is to cast * val to an int and call {@link #setElem(int, int)}. Subclasses can * override this method if another implementation is needed. * @param bank the specified bank * @param i the specified index * @param val the value to set the element in the specified bank * at the specified index of the data array * @see #getElemDouble(int) * @see #getElemDouble(int, int) */ public void setElemDouble(int bank, int i, double val) { setElem(bank,i,(int)val); } static int[] toIntArray(Object obj) { if (obj instanceof int[]) { return (int[])obj; } else if (obj == null) { return null; } else if (obj instanceof short[]) { short sdata[] = (short[])obj; int idata[] = new int[sdata.length]; for (int i = 0; i < sdata.length; i++) { idata[i] = (int)sdata[i] & 0xffff; } return idata; } else if (obj instanceof byte[]) { byte bdata[] = (byte[])obj; int idata[] = new int[bdata.length]; for (int i = 0; i < bdata.length; i++) { idata[i] = 0xff & (int)bdata[i]; } return idata; } return null; } static { SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() { public byte[] getData(DataBufferByte dbb, int bank) { return dbb.bankdata[bank]; } public short[] getData(DataBufferUShort dbus, int bank) { return dbus.bankdata[bank]; } public int[] getData(DataBufferInt dbi, int bank) { return dbi.bankdata[bank]; } public StateTrackableDelegate getTrackable(DataBuffer db) { return db.theTrackable; } }); } }