/* Copyright (C) 2000, 2002  Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.awt.image;

import gnu.java.awt.Buffers;

/* FIXME: This class does not yet support data type TYPE_SHORT */

/**
 * ComponentSampleModel supports a flexible organization of pixel samples in
 * memory, permitting pixel samples to be interleaved by band, by scanline,
 * and by pixel.
 *
 * A DataBuffer for this sample model has K banks of data.  Pixels have N
 * samples, so there are N bands in the DataBuffer.  Each band is completely
 * contained in one bank of data, but a bank may contain more than one band.
 * Each pixel sample is stored in a single data element.
 *
 * Within a bank, each band begins at an offset stored in bandOffsets.  The
 * banks containing the band is given by bankIndices.  Within the bank, there
 * are three dimensions - band, pixel, and scanline.  The dimension ordering
 * is controlled by bandOffset, pixelStride, and scanlineStride, which means
 * that any combination of interleavings is supported.
 *
 * @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;

    this.numBanks = 0;
    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_SHORT:
	    DataBufferShort inShort = (DataBufferShort) data;
	    short[] outShort = (short[]) obj;
	    if (outShort == null) outShort = new short[numBands];
		
	    for (int b=0; b<numBands; b++)
	      {
		int dOffset = totalBandDataOffsets[b];
		outShort[b] = inShort.getData(bankIndices[b])[dOffset];
	      }
	    return outShort;

	  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;

	  case DataBuffer.TYPE_FLOAT:
	    DataBufferFloat inFloat = (DataBufferFloat) data;
	    float[] outFloat = (float[]) obj;
	    if (outFloat == null) outFloat = new float[numBands];

	    for (int b=0; b<numBands; b++)
	      {
		int dOffset = totalBandDataOffsets[b];
		outFloat[b] = inFloat.getData(bankIndices[b])[dOffset];
	      }
	    return outFloat;
	    
	  case DataBuffer.TYPE_DOUBLE:
	    DataBufferDouble inDouble = (DataBufferDouble) data;
	    double[] outDouble = (double[]) obj;
	    if (outDouble == null) outDouble = new double[numBands];

	    for (int b=0; b<numBands; b++)
	      {
		int dOffset = totalBandDataOffsets[b];
		outDouble[b] = inDouble.getData(bankIndices[b])[dOffset];
	      }
	    return outDouble;
	    
	  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:
	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_SHORT:
	{
	  DataBufferShort out = (DataBufferShort) 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;
	}
      case DataBuffer.TYPE_FLOAT:
	{
	  DataBufferFloat out = (DataBufferFloat) data;
	  float[] in = (float[]) obj;
	  
	  for (int b=0; b<numBands; b++)
	    out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
	  
	  return;
	}
      case DataBuffer.TYPE_DOUBLE:
	{
	  DataBufferDouble out = (DataBufferDouble) data;
	  double[] in = (double[]) 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);
  }
}
