/*
* Portions Copyright 1997-2008 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;
}
public void setTrackable(DataBuffer db,
StateTrackableDelegate trackable)
{
db.theTrackable = trackable;
}
});
}
}