mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			436 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			436 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
/* Copyright (C) 2000  Free Software Foundation
 | 
						|
 | 
						|
   This file is part of libgcj.
 | 
						|
 | 
						|
This software is copyrighted work licensed under the terms of the
 | 
						|
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | 
						|
details.  */
 | 
						|
 | 
						|
package java.awt.image;
 | 
						|
 | 
						|
import gnu.gcj.awt.Buffers;
 | 
						|
 | 
						|
/* FIXME: This class does not yet support data type TYPE_SHORT */
 | 
						|
 | 
						|
/**
 | 
						|
 * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
 | 
						|
 */
 | 
						|
public class ComponentSampleModel extends SampleModel
 | 
						|
{
 | 
						|
  protected int[] bandOffsets;
 | 
						|
  protected int[] bankIndices;
 | 
						|
  
 | 
						|
  // FIXME: Should we really shadow the numBands in the superclass?
 | 
						|
  //protected int numBands;
 | 
						|
  
 | 
						|
  /** Used when creating data buffers. */
 | 
						|
  protected int numBanks;
 | 
						|
 | 
						|
  protected int scanlineStride;
 | 
						|
  
 | 
						|
  protected int pixelStride;
 | 
						|
  
 | 
						|
  private boolean tightPixelPacking = false;
 | 
						|
  
 | 
						|
  public ComponentSampleModel(int dataType,
 | 
						|
			      int w, int h,
 | 
						|
			      int pixelStride,
 | 
						|
			      int scanlineStride,
 | 
						|
			      int[] bandOffsets)
 | 
						|
  {
 | 
						|
    this(dataType, w, h, pixelStride, scanlineStride,
 | 
						|
	 new int[bandOffsets.length], bandOffsets);
 | 
						|
  }
 | 
						|
    
 | 
						|
  public ComponentSampleModel(int dataType,
 | 
						|
			      int w, int h,
 | 
						|
			      int pixelStride,
 | 
						|
			      int scanlineStride,
 | 
						|
			      int[] bankIndices,
 | 
						|
			      int[] bandOffsets)
 | 
						|
  {
 | 
						|
    super(dataType, w, h, bandOffsets.length);
 | 
						|
    if ((pixelStride<0) || (scanlineStride<0) || 
 | 
						|
	(bandOffsets.length<1) ||
 | 
						|
	(bandOffsets.length != bankIndices.length))
 | 
						|
      throw new IllegalArgumentException();
 | 
						|
    
 | 
						|
    this.bandOffsets = bandOffsets;
 | 
						|
    this.bankIndices = bankIndices;
 | 
						|
 | 
						|
    for (int b=0; b<bankIndices.length; b++)
 | 
						|
      this.numBanks = Math.max(this.numBanks, bankIndices[b]+1);
 | 
						|
 | 
						|
    this.scanlineStride = scanlineStride;
 | 
						|
    this.pixelStride = pixelStride;
 | 
						|
 | 
						|
    // See if we can use some speedups
 | 
						|
 | 
						|
    /* FIXME: May these checks should be reserved for the
 | 
						|
       PixelInterleavedSampleModel? */
 | 
						|
	
 | 
						|
    if (pixelStride == numBands)
 | 
						|
      {
 | 
						|
	tightPixelPacking = true;
 | 
						|
	for (int b=0; b<numBands; b++) {
 | 
						|
	  if ((bandOffsets[b] != b) || (bankIndices[b] !=0))
 | 
						|
	    {
 | 
						|
	      tightPixelPacking = false;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      }
 | 
						|
  }		
 | 
						|
 | 
						|
  public SampleModel createCompatibleSampleModel(int w, int h)
 | 
						|
  {
 | 
						|
    return new ComponentSampleModel(dataType, w, h, pixelStride,
 | 
						|
				    scanlineStride, bankIndices,
 | 
						|
				    bandOffsets);
 | 
						|
  }
 | 
						|
 | 
						|
  public SampleModel createSubsetSampleModel(int[] bands)
 | 
						|
  {
 | 
						|
    int numBands = bands.length;
 | 
						|
    
 | 
						|
    int[] bankIndices = new int[numBands];
 | 
						|
    int[] bandOffsets = new int[numBands];
 | 
						|
    for (int b=0; b<numBands; b++)
 | 
						|
      {
 | 
						|
	bankIndices[b] = this.bankIndices[bands[b]];
 | 
						|
	bandOffsets[b] = this.bandOffsets[bands[b]];
 | 
						|
      }
 | 
						|
 | 
						|
    return new ComponentSampleModel(dataType, width, height, pixelStride,
 | 
						|
				    scanlineStride, bankIndices,
 | 
						|
				    bandOffsets);
 | 
						|
  }
 | 
						|
 | 
						|
  public DataBuffer createDataBuffer()
 | 
						|
  {
 | 
						|
    // Maybe this value should be precalculated in the constructor?
 | 
						|
    int highestOffset = 0;
 | 
						|
    for (int b=0; b<numBands; b++)
 | 
						|
      {
 | 
						|
	highestOffset = Math.max(highestOffset, bandOffsets[b]);
 | 
						|
      }
 | 
						|
    int size = pixelStride*(width-1) + scanlineStride*(height-1) +
 | 
						|
      highestOffset + 1;
 | 
						|
    
 | 
						|
    return Buffers.createBuffer(getDataType(), size, numBanks);
 | 
						|
  }
 | 
						|
 | 
						|
  public int getOffset(int x, int y)
 | 
						|
  {
 | 
						|
    return getOffset(x, y, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  public int getOffset(int x, int y, int b)
 | 
						|
  {
 | 
						|
    return bandOffsets[b] + pixelStride*x + scanlineStride*y;
 | 
						|
  }
 | 
						|
 | 
						|
  public final int[] getSampleSize()
 | 
						|
  {
 | 
						|
    int size = DataBuffer.getDataTypeSize(getDataType());
 | 
						|
    int[] sizes = new int[numBands];
 | 
						|
 | 
						|
    java.util.Arrays.fill(sizes, size);
 | 
						|
    return sizes;
 | 
						|
  }
 | 
						|
 | 
						|
  public final int getSampleSize(int band)
 | 
						|
  {
 | 
						|
    return DataBuffer.getDataTypeSize(getDataType());
 | 
						|
  }
 | 
						|
 | 
						|
  public final int[] getBankIndices()
 | 
						|
  {
 | 
						|
    return bankIndices;
 | 
						|
  }
 | 
						|
 | 
						|
  public final int[] getBandOffsets()
 | 
						|
  {
 | 
						|
    return bandOffsets;
 | 
						|
  }
 | 
						|
 | 
						|
  public final int getScanlineStride()
 | 
						|
  {
 | 
						|
    return scanlineStride;
 | 
						|
  }
 | 
						|
 | 
						|
  public final int getPixelStride()
 | 
						|
  {
 | 
						|
    return pixelStride;
 | 
						|
  }
 | 
						|
 | 
						|
  public final int getNumDataElements()
 | 
						|
  {
 | 
						|
    return numBands;
 | 
						|
  }
 | 
						|
 | 
						|
  public Object getDataElements(int x, int y, Object obj, DataBuffer data)
 | 
						|
  {
 | 
						|
    int xyOffset = pixelStride*x + scanlineStride*y;
 | 
						|
    
 | 
						|
    int[] totalBandDataOffsets = new int[numBands];
 | 
						|
    
 | 
						|
    /* Notice that band and bank offsets are different. Band offsets
 | 
						|
       are managed by the sample model, and bank offsets are managed
 | 
						|
       by the data buffer. Both must be accounted for. */
 | 
						|
    
 | 
						|
    /* FIXME: For single pixels, it is probably easier to simple
 | 
						|
       call getElem instead of calculating the bank offset ourself.
 | 
						|
       
 | 
						|
       On the other hand, then we need to push the value through
 | 
						|
       the int type returned by the getElem method.  */
 | 
						|
    
 | 
						|
    int[] bankOffsets = data.getOffsets();
 | 
						|
    
 | 
						|
    for (int b=0; b<numBands; b++)
 | 
						|
      {
 | 
						|
	totalBandDataOffsets[b] = 
 | 
						|
	  bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset;
 | 
						|
      }
 | 
						|
	
 | 
						|
    try
 | 
						|
      {
 | 
						|
	switch (getTransferType())
 | 
						|
	  {
 | 
						|
	  case DataBuffer.TYPE_BYTE:
 | 
						|
	    DataBufferByte inByte = (DataBufferByte) data;
 | 
						|
	    byte[] outByte = (byte[]) obj;
 | 
						|
	    if (outByte == null) outByte = new byte[numBands];
 | 
						|
		
 | 
						|
	    for (int b=0; b<numBands; b++)
 | 
						|
	      {
 | 
						|
		int dOffset = totalBandDataOffsets[b];
 | 
						|
		outByte[b] = inByte.getData(bankIndices[b])[dOffset];
 | 
						|
	      }
 | 
						|
	    return outByte;
 | 
						|
		
 | 
						|
	  case DataBuffer.TYPE_USHORT:
 | 
						|
	    DataBufferUShort inUShort = (DataBufferUShort) data;
 | 
						|
	    short[] outUShort = (short[]) obj;
 | 
						|
	    if (outUShort == null) outUShort = new short[numBands];
 | 
						|
		
 | 
						|
	    for (int b=0; b<numBands; b++)
 | 
						|
	      {
 | 
						|
		int dOffset = totalBandDataOffsets[b];
 | 
						|
		outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
 | 
						|
	      }
 | 
						|
	    return outUShort;
 | 
						|
 | 
						|
	  case DataBuffer.TYPE_INT:
 | 
						|
	    DataBufferInt inInt = (DataBufferInt) data;
 | 
						|
	    int[] outInt = (int[]) obj;
 | 
						|
	    if (outInt == null) outInt = new int[numBands];
 | 
						|
		
 | 
						|
	    for (int b=0; b<numBands; b++)
 | 
						|
	      {
 | 
						|
		int dOffset = totalBandDataOffsets[b];
 | 
						|
		outInt[b] = inInt.getData(bankIndices[b])[dOffset];
 | 
						|
	      }
 | 
						|
	    return outInt;
 | 
						|
		
 | 
						|
	    // FIXME: Fill in the other possible types.
 | 
						|
	  default:
 | 
						|
	      throw new IllegalStateException("unknown transfer type " +
 | 
						|
					      getTransferType());
 | 
						|
	  }
 | 
						|
      }
 | 
						|
    catch (ArrayIndexOutOfBoundsException aioobe)
 | 
						|
      {
 | 
						|
	String msg = "While reading data elements, " +
 | 
						|
	  "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
 | 
						|
	  ", data.getSize()=" + data.getSize() + ": " + aioobe;
 | 
						|
	throw new ArrayIndexOutOfBoundsException(msg);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public Object getDataElements(int x, int y, int w, int h, Object obj,
 | 
						|
				DataBuffer data)
 | 
						|
  {
 | 
						|
    if (!tightPixelPacking)
 | 
						|
      {
 | 
						|
	return super.getDataElements(x, y, w, h, obj, data);
 | 
						|
      }
 | 
						|
 | 
						|
    // using get speedup
 | 
						|
    
 | 
						|
    // We can copy whole rows
 | 
						|
    int rowSize = w*numBands;
 | 
						|
    int dataSize = rowSize*h;
 | 
						|
    
 | 
						|
    DataBuffer transferBuffer =
 | 
						|
      Buffers.createBuffer(getTransferType(), obj, dataSize);
 | 
						|
    obj = Buffers.getData(transferBuffer);
 | 
						|
 | 
						|
    int inOffset =
 | 
						|
      pixelStride*x +
 | 
						|
      scanlineStride*y +
 | 
						|
      data.getOffset(); // Assumes only one band is used
 | 
						|
 | 
						|
    /* We don't add band offsets since we assume that bands have
 | 
						|
       offsets 0, 1, 2, ... */
 | 
						|
 | 
						|
    // See if we can copy everything in one go
 | 
						|
    if (scanlineStride == rowSize)
 | 
						|
      {
 | 
						|
	// Collapse scan lines:
 | 
						|
	rowSize *= h;
 | 
						|
	// We ignore scanlineStride since it won't be of any use
 | 
						|
	h = 1;
 | 
						|
      }
 | 
						|
 | 
						|
    int outOffset = 0;
 | 
						|
    Object inArray = Buffers.getData(data);
 | 
						|
    for (int yd = 0; yd<h; yd++)
 | 
						|
      {
 | 
						|
	System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
 | 
						|
	inOffset  += scanlineStride;
 | 
						|
	outOffset += rowSize;
 | 
						|
      }
 | 
						|
    return obj;
 | 
						|
  }
 | 
						|
 | 
						|
  public void setDataElements(int x, int y, int w, int h,
 | 
						|
			      Object obj, DataBuffer data)
 | 
						|
  {
 | 
						|
    if (!tightPixelPacking)
 | 
						|
      {
 | 
						|
	super.setDataElements(x, y, w, h, obj, data);
 | 
						|
	return;
 | 
						|
      }
 | 
						|
 | 
						|
    // using set speedup, we can copy whole rows
 | 
						|
    int rowSize = w*numBands;
 | 
						|
    int dataSize = rowSize*h;
 | 
						|
    
 | 
						|
    DataBuffer transferBuffer =
 | 
						|
      Buffers.createBufferFromData(getTransferType(), obj, dataSize);
 | 
						|
 | 
						|
    int[] bankOffsets = data.getOffsets();
 | 
						|
 | 
						|
    int outOffset =
 | 
						|
      pixelStride*x +
 | 
						|
      scanlineStride*y +
 | 
						|
      bankOffsets[0]; // same assuptions as in get...
 | 
						|
 | 
						|
    // See if we can copy everything in one go
 | 
						|
    if (scanlineStride == rowSize)
 | 
						|
      {
 | 
						|
	// Collapse scan lines:
 | 
						|
	scanlineStride = rowSize *= h;
 | 
						|
	h = 1;
 | 
						|
      }
 | 
						|
 | 
						|
    int inOffset = 0;
 | 
						|
    Object outArray = Buffers.getData(data);
 | 
						|
    for (int yd = 0; yd<h; yd++)
 | 
						|
      {
 | 
						|
	System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
 | 
						|
	outOffset += scanlineStride;
 | 
						|
	inOffset  += rowSize;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
 | 
						|
  {
 | 
						|
    int offset = pixelStride*x + scanlineStride*y;
 | 
						|
    if (iArray == null) iArray = new int[numBands];
 | 
						|
    for (int b=0; b<numBands; b++)
 | 
						|
      {
 | 
						|
	iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]);
 | 
						|
      }
 | 
						|
    return iArray;
 | 
						|
  }
 | 
						|
 | 
						|
  public int[] getPixels(int x, int y, int w, int h, int[] iArray,
 | 
						|
			 DataBuffer data)
 | 
						|
  {
 | 
						|
    int offset = pixelStride*x + scanlineStride*y;
 | 
						|
    if (iArray == null) iArray = new int[numBands*w*h];
 | 
						|
    int outOffset = 0;
 | 
						|
    for (y=0; y<h; y++)
 | 
						|
      {
 | 
						|
	int lineOffset = offset;
 | 
						|
	for (x=0; x<w; x++)
 | 
						|
	  {
 | 
						|
	    for (int b=0; b<numBands; b++)
 | 
						|
	      {
 | 
						|
		iArray[outOffset++] = 
 | 
						|
		  data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
 | 
						|
	      }
 | 
						|
	    lineOffset += pixelStride;
 | 
						|
	  }
 | 
						|
	offset += scanlineStride;
 | 
						|
      }
 | 
						|
    return iArray;
 | 
						|
  }
 | 
						|
    
 | 
						|
  public int getSample(int x, int y, int b, DataBuffer data)
 | 
						|
  {
 | 
						|
    return data.getElem(bankIndices[b], getOffset(x, y, b));
 | 
						|
  }
 | 
						|
 | 
						|
  public void setDataElements(int x, int y, Object obj, DataBuffer data)
 | 
						|
  {
 | 
						|
    int offset = pixelStride*x + scanlineStride*y;
 | 
						|
    int[] totalBandDataOffsets = new int[numBands];
 | 
						|
    int[] bankOffsets = data.getOffsets();
 | 
						|
    for (int b=0; b<numBands; b++)
 | 
						|
      totalBandDataOffsets[b] =
 | 
						|
	bandOffsets[b]+bankOffsets[bankIndices[b]] + offset;
 | 
						|
 | 
						|
    switch (getTransferType())
 | 
						|
      {
 | 
						|
      case DataBuffer.TYPE_BYTE:
 | 
						|
	{
 | 
						|
	  DataBufferByte out = (DataBufferByte) data;
 | 
						|
	  byte[] in = (byte[]) obj;
 | 
						|
	  
 | 
						|
	  for (int b=0; b<numBands; b++)
 | 
						|
	    out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
 | 
						|
	  
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
      case DataBuffer.TYPE_USHORT:
 | 
						|
	{
 | 
						|
	  DataBufferUShort out = (DataBufferUShort) data;
 | 
						|
	  short[] in = (short[]) obj;
 | 
						|
	  
 | 
						|
	  for (int b=0; b<numBands; b++)
 | 
						|
	    out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
 | 
						|
	  
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
      case DataBuffer.TYPE_INT:
 | 
						|
	{
 | 
						|
	  DataBufferInt out = (DataBufferInt) data;
 | 
						|
	  int[] in = (int[]) obj;
 | 
						|
	  
 | 
						|
	  for (int b=0; b<numBands; b++)
 | 
						|
	    out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
 | 
						|
	  
 | 
						|
	  return;
 | 
						|
	}
 | 
						|
      default:
 | 
						|
	throw new UnsupportedOperationException("transfer type not " +
 | 
						|
						"implemented");
 | 
						|
      }
 | 
						|
  }
 | 
						|
  
 | 
						|
  public void setPixel(int x, int y, int[] iArray, DataBuffer data)
 | 
						|
  {
 | 
						|
    int offset = pixelStride*x + scanlineStride*y;
 | 
						|
    for (int b=0; b<numBands; b++)
 | 
						|
      data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]);
 | 
						|
  }
 | 
						|
    
 | 
						|
  public void setSample(int x, int y, int b, int s, DataBuffer data)
 | 
						|
  {
 | 
						|
    data.setElem(bankIndices[b], getOffset(x, y, b), s);
 | 
						|
  }
 | 
						|
}
 |