/* Copyright (C) 2000, 2002, 2003, 2004, 2006,  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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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 java.util.Arrays;

import gnu.java.awt.BitMaskExtent;
import gnu.java.lang.CPStringBuilder;

/**
 * A <code>SampleModel</code> used when all samples are stored in a single
 * data element in the {@link DataBuffer}, and each data element contains 
 * samples for one pixel only.
 * 
 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
 */
public class SinglePixelPackedSampleModel extends SampleModel
{
  private int scanlineStride;
  private int[] bitMasks;
  private int[] bitOffsets;
  private int[] sampleSize;
  
  /**
   * Creates a new <code>SinglePixelPackedSampleModel</code>.
   * 
   * @param dataType  the data buffer type.
   * @param w  the width (in pixels).
   * @param h  the height (in pixels).
   * @param bitMasks  an array containing the bit mask used to extract the
   *     sample value for each band.
   */
  public SinglePixelPackedSampleModel(int dataType, int w, int h,
				      int[] bitMasks)
  {
    this(dataType, w, h, w, bitMasks);
  }

  /**
   * Creates a new <code>SinglePixelPackedSampleModel</code>.
   * 
   * @param dataType  the data buffer type.
   * @param w  the width (in pixels).
   * @param h  the height (in pixels).
   * @param scanlineStride  the number of data elements between a pixel on one
   *     row and the corresponding pixel on the next row.
   * @param bitMasks  an array containing the bit mask used to extract the
   *     sample value for each band.
   */
  public SinglePixelPackedSampleModel(int dataType, int w, int h,
				      int scanlineStride, int[] bitMasks)
  {
    super(dataType, w, h, bitMasks.length);

    switch (dataType)
      {
      case DataBuffer.TYPE_BYTE:
      case DataBuffer.TYPE_USHORT:
      case DataBuffer.TYPE_INT:
	break;
      default:
        throw new IllegalArgumentException(
            "SinglePixelPackedSampleModel unsupported dataType");
      }
    
    this.scanlineStride = scanlineStride;
    this.bitMasks = bitMasks;
    
    bitOffsets = new int[numBands];
    sampleSize = new int[numBands];
    
    BitMaskExtent extent = new BitMaskExtent();
    for (int b = 0; b < numBands; b++)
      {
        // the mask is an unsigned integer
        long mask = bitMasks[b] & 0xFFFFFFFFL;
        extent.setMask(mask);
        sampleSize[b] = extent.bitWidth;
        bitOffsets[b] = extent.leastSignificantBit;
      }
  }

  /**
   * Returns the number of data elements.
   * 
   * @return <code>1</code>.
   */
  public int getNumDataElements()
  {
    return 1;
  }

  /**
   * Creates a new <code>SampleModel</code> that is compatible with this
   * model and has the specified width and height.
   * 
   * @param w  the width (in pixels).
   * @param h  the height (in pixels).
   * 
   * @return The new sample model.
   */
  public SampleModel createCompatibleSampleModel(int w, int h)
  {
    /* FIXME: We can avoid recalculation of bit offsets and sample
       sizes here by passing these from the current instance to a
       special private constructor. */
    return new SinglePixelPackedSampleModel(dataType, w, h, bitMasks);
  }


  /**
   * Creates a DataBuffer for holding pixel data in the format and
   * layout described by this SampleModel. The returned buffer will
   * consist of one single bank.
   * 
   * @return The data buffer.
   */
  public DataBuffer createDataBuffer()
  {
    // We can save (scanlineStride - width) pixels at the very end of
    // the buffer. The Sun reference implementation (J2SE 1.3.1 and
    // 1.4.1_01) seems to do this; tested with Mauve test code.
    int size = scanlineStride * (height - 1) + width;

    DataBuffer buffer = null;
    switch (getTransferType())
      {
      case DataBuffer.TYPE_BYTE:
        buffer = new DataBufferByte(size);
        break;
      case DataBuffer.TYPE_USHORT:
        buffer = new DataBufferUShort(size);
        break;
      case DataBuffer.TYPE_INT:
        buffer = new DataBufferInt(size);
        break;
      }
    return buffer;
  }

  /**
   * Returns an array containing the size (in bits) for each band accessed by
   * the <code>SampleModel</code>.
   * 
   * @return An array.
   * 
   * @see #getSampleSize(int)
   */
  public int[] getSampleSize()
  {
    return (int[]) sampleSize.clone();
  }
  
  /**
   * Returns the size (in bits) of the samples for the specified band.
   * 
   * @param band  the band (in the range <code>0</code> to 
   *     <code>getNumBands() - 1</code>).
   *     
   * @return The sample size (in bits).
   */
  public int getSampleSize(int band)
  {
    return sampleSize[band];
  }

  /**
   * Returns the index in the data buffer that stores the pixel at (x, y).
   * 
   * @param x  the x-coordinate.
   * @param y  the y-coordinate.
   * 
   * @return The index in the data buffer that stores the pixel at (x, y).
   */
  public int getOffset(int x, int y)
  {
    return scanlineStride*y + x;
  }

  public int[] getBitOffsets()
  {
    return bitOffsets;
  }

  public int[] getBitMasks()
  {
    return bitMasks;
  }

  /**
   * Returns the number of data elements from a pixel in one row to the
   * corresponding pixel in the next row.
   * 
   * @return The scanline stride.
   */
  public int getScanlineStride()
  {
    return scanlineStride;
  }

  /**
   * Creates a new <code>SinglePixelPackedSampleModel</code> that accesses
   * the specified subset of bands.
   * 
   * @param bands  an array containing band indices (<code>null</code> not
   *     permitted).
   * 
   * @return A new sample model.
   * 
   * @throws NullPointerException if <code>bands</code> is <code>null</code>.
   * @throws RasterFormatException if <code>bands.length</code> is greater
   *     than the number of bands in this model.
   */
  public SampleModel createSubsetSampleModel(int[] bands)
  {
    if (bands.length > numBands)
      throw new RasterFormatException("Too many bands.");
    
    int numBands = bands.length;
    
    int[] bitMasks = new int[numBands];

    for (int b = 0; b < numBands; b++)
      bitMasks[b] = this.bitMasks[bands[b]];

    return new SinglePixelPackedSampleModel(dataType, width, height,
					    scanlineStride, bitMasks);
  }

  public Object getDataElements(int x, int y, Object obj,
				DataBuffer data)
  {
    int type = getTransferType();
    Object ret = null;
    switch (type)
      {
      case DataBuffer.TYPE_BYTE:
        {
          byte[] in = (byte[]) obj;
          if (in == null)
            in = new byte[1];
          in[0] = (byte) data.getElem(x + y * scanlineStride);
          ret = in;
        }
        break;
      case DataBuffer.TYPE_USHORT:
        {
          short[] in = (short[]) obj;
          if (in == null)
            in = new short[1];
          in[0] = (short) data.getElem(x + y * scanlineStride);
          ret = in;
        }
        break;
      case DataBuffer.TYPE_INT:
        {
          int[] in = (int[]) obj;
          if (in == null)
            in = new int[1];
          in[0] = data.getElem(x + y * scanlineStride);
          ret = in;
        }
        break;
      }
    return ret;
  }
  
  /**
   * Returns an array containing the samples for the pixel at (x, y) in the
   * specified data buffer.  If <code>iArray</code> is not <code>null</code>,
   * it will be populated with the sample values and returned as the result of
   * this function (this avoids allocating a new array instance).
   * 
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
   * @param iArray  an array to populate with the sample values and return as 
   *     the result (if <code>null</code>, a new array will be allocated).
   * @param data  the data buffer (<code>null</code> not permitted).
   * 
   * @return The pixel sample values.
   * 
   * @throws NullPointerException if <code>data</code> is <code>null</code>.
   */
  public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
  {
    int offset = scanlineStride*y + x;
    if (iArray == null) iArray = new int[numBands];
    int samples = data.getElem(offset);

    for (int b = 0; b < numBands; b++)
      iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
	
    return iArray;
  }

  /**
   * Returns an array containing the samples for the pixels in the region 
   * specified by (x, y, w, h) in the specified data buffer.  The array is
   * ordered by pixels (that is, all the samples for the first pixel are 
   * grouped together, followed by all the samples for the second pixel, and so
   * on).  If <code>iArray</code> is not <code>null</code>, it will be 
   * populated with the sample values and returned as the result of this 
   * function (this avoids allocating a new array instance).
   * 
   * @param x  the x-coordinate of the top-left pixel.
   * @param y  the y-coordinate of the top-left pixel.
   * @param w  the width of the region of pixels.
   * @param h  the height of the region of pixels.
   * @param iArray  an array to populate with the sample values and return as 
   *     the result (if <code>null</code>, a new array will be allocated).
   * @param data  the data buffer (<code>null</code> not permitted).
   * 
   * @return The pixel sample values.
   * 
   * @throws NullPointerException if <code>data</code> is <code>null</code>.
   */
  public int[] getPixels(int x, int y, int w, int h, int[] iArray,
			 DataBuffer data)
  {
    int offset = scanlineStride*y + x;
    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++)
	  {
	    int samples = data.getElem(lineOffset++);
	    for (int b = 0; b < numBands; b++)
	      iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
	  }
	offset += scanlineStride;
      }
    return iArray;	
  }

  /**
   * Returns the sample value for the pixel at (x, y) in the specified data 
   * buffer.
   * 
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
   * @param b  the band (in the range <code>0</code> to 
   *     <code>getNumBands() - 1</code>).
   * @param data  the data buffer (<code>null</code> not permitted).
   * 
   * @return The sample value.
   * 
   * @throws NullPointerException if <code>data</code> is <code>null</code>.
   */
  public int getSample(int x, int y, int b, DataBuffer data)
  {
    int offset = scanlineStride*y + x;
    int samples = data.getElem(offset);
    return (samples & bitMasks[b]) >>> bitOffsets[b];
  }
  
  public void setDataElements(int x, int y, Object obj, DataBuffer data)
  {
    int transferType = getTransferType();
    switch (transferType)
      {
      case DataBuffer.TYPE_BYTE:
        {
          byte[] in = (byte[]) obj;
          data.setElem(y * scanlineStride + x, ((int) in[0]) & 0xff);
        }
        break;
      case DataBuffer.TYPE_USHORT:
        {
          short[] in = (short[]) obj;
          data.setElem(y * scanlineStride + x, ((int) in[0]) & 0xffff);
        }
        break;
      case DataBuffer.TYPE_INT:
        {
          int[] in = (int[]) obj;
          data.setElem(y * scanlineStride + x, in[0]);
          break;
        }
      }
  }

  /**
   * Sets the samples for the pixel at (x, y) in the specified data buffer to
   * the specified values. 
   * 
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
   * @param iArray  the sample values (<code>null</code> not permitted).
   * @param data  the data buffer (<code>null</code> not permitted).
   * 
   * @throws NullPointerException if either <code>iArray</code> or 
   *     <code>data</code> is <code>null</code>.
   */
  public void setPixel(int x, int y, int[] iArray, DataBuffer data)
  {
    int offset = scanlineStride*y + x;
    
    int samples = 0;
    for (int b = 0; b < numBands; b++)
      samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];

    data.setElem(offset, samples);
  }

  /**
   * This method implements a more efficient way to set pixels than the default
   * implementation of the super class. It copies the pixel components directly
   * from the input array instead of creating a intermediate buffer.
   * @param x The x-coordinate of the pixel rectangle in <code>obj</code>.
   * @param y The y-coordinate of the pixel rectangle in <code>obj</code>.
   * @param w The width of the pixel rectangle in <code>obj</code>.
   * @param h The height of the pixel rectangle in <code>obj</code>.
   * @param iArray The primitive array containing the pixels to set.
   * @param data The DataBuffer to store the pixels into.
   * @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[], 
   *     java.awt.image.DataBuffer)
   */
  public void setPixels(int x, int y, int w, int h, int[] iArray,
						DataBuffer data)
  {
    int inOffset = 0;
    for (int yy=y; yy<(y+h); yy++)
     {
      int offset = scanlineStride*yy + x;
      for (int xx=x; xx<(x+w); xx++)
       { 
        int samples = 0;
        for (int b = 0; b < numBands; b++)
          samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b];
        data.setElem(0, offset, samples);
        inOffset += numBands;
        offset += 1;
      }
    }
  }
  
  /**
   * Sets the sample value for a band for the pixel at (x, y) in the 
   * specified data buffer. 
   * 
   * @param x  the x-coordinate of the pixel.
   * @param y  the y-coordinate of the pixel.
   * @param b  the band (in the range <code>0</code> to 
   *     <code>getNumBands() - 1</code>).
   * @param s  the sample value.
   * @param data  the data buffer (<code>null</code> not permitted).
   * 
   * @throws NullPointerException if <code>data</code> is <code>null</code>.
   */
  public void setSample(int x, int y, int b, int s, DataBuffer data)
  {
    int offset = scanlineStride*y + x;
    int samples = data.getElem(offset);
    int bitMask = bitMasks[b];
    samples &= ~bitMask;
    samples |= (s << bitOffsets[b]) & bitMask;
    data.setElem(offset, samples);
  }
  
  /**
   * Tests this sample model for equality with an arbitrary object.  This 
   * method returns <code>true</code> if and only if:
   * <ul>
   *   <li><code>obj</code> is not <code>null</code>;
   *   <li><code>obj</code> is an instance of 
   *       <code>SinglePixelPackedSampleModel</code>;
   *   <li>both models have the same:
   *     <ul>
   *       <li><code>dataType</code>;
   *       <li><code>width</code>;
   *       <li><code>height</code>;
   *       <li><code>numBands</code>;
   *       <li><code>scanlineStride</code>;
   *       <li><code>bitMasks</code>;
   *       <li><code>bitOffsets</code>.
   *     </ul>
   *   </li>
   * </ul>
   * 
   * @param obj  the object (<code>null</code> permitted)
   * 
   * @return <code>true</code> if this model is equal to <code>obj</code>, and
   *     <code>false</code> otherwise.
   */
  public boolean equals(Object obj) 
  {
    if (this == obj) 
      return true;
    if (! (obj instanceof SinglePixelPackedSampleModel)) 
      return false;
    SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel) obj;
    if (this.dataType != that.dataType)
      return false;
    if (this.width != that.width)
      return false;
    if (this.height != that.height)
      return false;
    if (this.numBands != that.numBands)
      return false;
    if (this.scanlineStride != that.scanlineStride)
      return false;
    if (!Arrays.equals(this.bitMasks, that.bitMasks))
      return false;
    if (!Arrays.equals(this.bitOffsets, that.bitOffsets)) 
      return false;
    return true;
  }
  
  /**
   * Returns a hash code for this <code>SinglePixelPackedSampleModel</code>.
   * 
   * @return A hash code.
   */
  public int hashCode()
  {
    // this hash code won't match Sun's, but that shouldn't matter...
    int result = 193;
    result = 37 * result + dataType;
    result = 37 * result + width;
    result = 37 * result + height;
    result = 37 * result + numBands;
    result = 37 * result + scanlineStride;
    for (int i = 0; i < bitMasks.length; i++)
      result = 37 * result + bitMasks[i];
    for (int i = 0; i < bitOffsets.length; i++)
      result = 37 * result + bitOffsets[i];
    return result;
  }
  
  /**
   * Creates a String with some information about this SampleModel.
   * @return A String describing this SampleModel.
   * @see java.lang.Object#toString()
   */
  public String toString()
  {
    CPStringBuilder result = new CPStringBuilder();
    result.append(getClass().getName());
    result.append("[");
    result.append("scanlineStride=").append(scanlineStride);
    for(int i = 0; i < bitMasks.length; i+=1)
    {
      result.append(", mask[").append(i).append("]=0x").append(
          Integer.toHexString(bitMasks[i]));
    }
    
    result.append("]");
    return result.toString();
  }
}
