/* CairoSurface.java
   Copyright (C) 2006, 2007 Free Software Foundation, Inc.

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 gnu.java.awt.peer.gtk;

import gnu.java.awt.Buffers;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.RasterFormatException;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Hashtable;

/**
 * CairoSurface - wraps a Cairo surface.
 *
 * @author Sven de Marothy
 */
public class CairoSurface extends WritableRaster
{
  int width = -1, height = -1;

  /**
   * The native pointer to the Cairo surface.
   */
  long surfacePointer;

  /**
   * Whether the data buffer is shared between java and cairo.
   */
  boolean sharedBuffer;

  // FIXME: use only the cairoCM_pre colormodel
  // since that's what Cairo really uses (is there a way to do this cheaply?
  // we use a non-multiplied model most of the time to avoid costly coercion
  // operations...)
  static ColorModel cairoColorModel = new DirectColorModel(32, 0x00FF0000,
                                                           0x0000FF00,
                                                           0x000000FF,
                                                           0xFF000000);

  static ColorModel cairoCM_pre = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                                       32, 0x00FF0000,
                                                       0x0000FF00,
                                                       0x000000FF,
                                                       0xFF000000,
                                                       true,
                                                       Buffers.smallestAppropriateTransferType(32));

  // This CM corresponds to the CAIRO_FORMAT_RGB24 type in Cairo
  static ColorModel cairoCM_opaque = new DirectColorModel(24, 0x00FF0000,
                                                          0x0000FF00,
                                                          0x000000FF);
  /**
   * Allocates and clears the buffer and creates the cairo surface.
   * @param width - the image size
   * @param height - the image size
   * @param stride - the buffer row stride. (in ints)
   */
  private native void create(int width, int height, int stride, int[] buf);

  /**
   * Destroys the cairo surface and frees the buffer.
   */
  private native void destroy(long surfacePointer, int[] buf);

  /**
   * Draws this image to a given CairoGraphics context,
   * with an affine transform given by i2u.
   */
  public native void nativeDrawSurface(long surfacePointer, long contextPointer,
                                       double[] i2u, double alpha,
                                       int interpolation);

  /**
   * Synchronizes the image's data buffers, copying any changes made in the
   * Java array into the native array.
   *
   * This method should only be called if (sharedBuffers == false).
   */
  native void syncNativeToJava(long surfacePointer, int[] buffer);

  /**
   * Synchronizes the image's data buffers, copying any changes made in the
   * native array into the Java array.
   *
   * This method should only be called if (sharedBuffers == false).
   */
  native void syncJavaToNative(long surfacePointer, int[] buffer);

  /**
   * Return the buffer, with the sample values of each pixel reversed
   * (ie, in ABGR instead of ARGB).
   *
   * @return A pointer to a flipped buffer.  The memory is allocated in native
   *        code, and must be explicitly freed when it is no longer needed.
   */
  native long getFlippedBuffer(long surfacePointer);

  /**
   * Create a cairo_surface_t with specified width and height.
   * The format will be ARGB32 with premultiplied alpha and native bit
   * and word ordering.
   */
  public CairoSurface(int width, int height)
  {
    this(0, 0, width, height);
  }

  public CairoSurface(int x, int y, int width, int height)
  {
    super(createCairoSampleModel(width, height), null, new Point(x, y));

    if(width <= 0 || height <= 0)
      throw new IllegalArgumentException("Image must be at least 1x1 pixels.");

    this.width = width;
    this.height = height;
    dataBuffer = new DataBufferInt(width * height);
    create(width, height, width, getData());

    if(surfacePointer == 0)
      throw new Error("Could not allocate bitmap.");
  }

  /**
   * Create a Cairo Surface that is a subimage of another Cairo Surface
   */
  public CairoSurface(SampleModel sm, CairoSurface parent, Rectangle bounds,
                      Point origin)
  {
    super(sm, parent.dataBuffer, bounds, origin, parent);

    this.width = super.width;
    this.height = super.height;
    this.surfacePointer = parent.surfacePointer;
    this.sharedBuffer = parent.sharedBuffer;
    this.dataBuffer = parent.dataBuffer;
  }

  /**
   * Create a cairo_surface_t from a GtkImage instance.
   * (data is copied, not shared)
   */
  CairoSurface(GtkImage image)
  {
    this(image.width, image.height);

    // Copy the pixel data from the GtkImage.
    int[] data = image.getPixels();

    // Swap ordering from GdkPixbuf to Cairo
    if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
      {
        for (int i = 0; i < data.length; i++ )
          {
            // On a big endian system we get a RRGGBBAA data array.
            int alpha = data[i] & 0xFF;
            if( alpha == 0 ) // I do not know why we need this, but it works.
              data[i] = 0;
            else
              {
                // Cairo needs a ARGB32 native array.
                data[i] = (data[i] >>> 8) | (alpha << 24);
              }
          }
      }
    else
      {
        for (int i = 0; i < data.length; i++ )
          {
            // On a little endian system we get a AABBGGRR data array.
            int alpha = data[i] & 0xFF000000;
            if( alpha == 0 ) // I do not know why we need this, but it works.
              data[i] = 0;
            else
              {
                int b = (data[i] & 0xFF0000) >> 16;
                int g = (data[i] & 0xFF00);
                int r = (data[i] & 0xFF) << 16;
                // Cairo needs a ARGB32 native array.
                data[i] = alpha | r | g | b;
              }
          }
      }

    System.arraycopy(data, 0, getData(), 0, data.length);
  }

  /**
   * Dispose of the native data.
   */
  public void dispose()
  {
    if(surfacePointer != 0 && parent == null)
      destroy(surfacePointer, getData());
  }

  /**
   * Call dispose() to clean up any native resources allocated.
   */
  protected void finalize()
  {
    dispose();
  }

  /**
   * Return a GtkImage from this Cairo surface.
   */
  public GtkImage getGtkImage()
  {
    return new GtkImage(width, height, getFlippedBuffer(surfacePointer));
  }

  /**
   * Convenience method to quickly grab the data array backing this Raster.
   *
   * @return The array behind the databuffer.
   */
  public int[] getData()
  {
    return ((DataBufferInt)dataBuffer).getData();
  }

  /**
   * Returns a BufferedImage backed by a Cairo surface.
   */
  public static BufferedImage getBufferedImage(int width, int height)
  {
    return getBufferedImage(new CairoSurface(width, height));
  }

  /**
   * Returns a BufferedImage backed by a Cairo surface,
   * created from a GtkImage.
   */
  public static BufferedImage getBufferedImage(GtkImage image)
  {
    return getBufferedImage(new CairoSurface(image));
  }

  /**
   * Returns a BufferedImage backed by a Cairo surface.
   */
  public static BufferedImage getBufferedImage(CairoSurface surface)
  {
    return new BufferedImage(cairoColorModel, surface,
                             cairoColorModel.isAlphaPremultiplied(),
                             new Hashtable());
  }

  /**
   * Return a Graphics2D drawing to the CairoSurface.
   */
  public Graphics2D getGraphics()
  {
    return new CairoSurfaceGraphics(this);
  }

  ///// Methods used by CairoSurfaceGraphics /////
  /**
   * Creates a cairo_t drawing context, returns the pointer as a long.
   * Used by CairoSurfaceGraphics.
   */
  native long nativeNewCairoContext(long surfacePointer);

  public long newCairoContext()
  {
    return nativeNewCairoContext(surfacePointer);
  }

  /**
   * Copy a portion of this surface to another area on the surface.  The given
   * parameters must be within bounds - count on a segfault otherwise.
   *
   * @param x The x coordinate of the area to be copied from.
   * @param y The y coordinate of the area to be copied from.
   * @param width The width of the area to be copied.
   * @param height The height of the area to be copied.
   * @param dx The destination x coordinate.
   * @param dy The destination y coordinate.
   * @param stride The scanline stride.
   */
  public void copyAreaNative(int x, int y, int width,
                             int height, int dx, int dy, int stride)
  {
    copyAreaNative2(surfacePointer, x, y, width, height, dx, dy, stride);
  }
  native void copyAreaNative2(long surfacePointer,
                              int x, int y, int width, int height,
                              int dx, int dy, int stride);

  /**
   * Creates a SampleModel that matches Cairo's native format
   */
  protected static SampleModel createCairoSampleModel(int w, int h)
  {
    return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h,
                                            new int[]{0x00FF0000, 0x0000FF00,
                                                      0x000000FF, 0xFF000000});
  }

  /**
   * Returns whether this ColorModel is compatible with Cairo's native types.
   *
   * @param cm The color model to check.
   * @return Whether it is compatible.
   */
  public static boolean isCompatibleColorModel(ColorModel cm)
  {
    return (cm.equals(cairoCM_pre) || cm.equals(cairoCM_opaque) ||
            cm.equals(cairoColorModel));
  }

  /**
   * Returns whether this SampleModel is compatible with Cairo's native types.
   *
   * @param sm The sample model to check.
   * @return Whether it is compatible.
   */
  public static boolean isCompatibleSampleModel(SampleModel sm)
  {
    return (sm instanceof SinglePixelPackedSampleModel
        && sm.getDataType() == DataBuffer.TYPE_INT
        && Arrays.equals(((SinglePixelPackedSampleModel)sm).getBitMasks(),
                         new int[]{0x00FF0000, 0x0000FF00,
                                   0x000000FF, 0xFF000000}));
  }

  ///// Methods interhited from Raster and WritableRaster /////
  public Raster createChild(int parentX, int parentY, int width, int height,
                            int childMinX, int childMinY, int[] bandList)
  {
    return createWritableChild(parentX, parentY, width, height,
                               childMinX, childMinY, bandList);
  }

  public WritableRaster createCompatibleWritableRaster()
  {
    return new CairoSurface(width, height);
  }

  public WritableRaster createCompatibleWritableRaster (int x, int y,
                                                        int w, int h)
  {
    return new CairoSurface(x, y, w, h);
  }

  public Raster createTranslatedChild(int childMinX, int childMinY)
  {
    return createWritableTranslatedChild(childMinX, childMinY);
  }

  public WritableRaster createWritableChild(int parentX, int parentY,
                                            int w, int h, int childMinX,
                                            int childMinY, int[] bandList)
  {
    if (parentX < minX || parentX + w > minX + width
        || parentY < minY || parentY + h > minY + height)
      throw new RasterFormatException("Child raster extends beyond parent");

    SampleModel sm = (bandList == null) ?
      sampleModel :
      sampleModel.createSubsetSampleModel(bandList);

    return new CairoSurface(sm, this,
                            new Rectangle(childMinX, childMinY, w, h),
                            new Point(sampleModelTranslateX + childMinX - parentX,
                                      sampleModelTranslateY + childMinY - parentY));
  }

  public WritableRaster createWritableTranslatedChild(int x, int y)
  {
    int tcx = sampleModelTranslateX - minX + x;
    int tcy = sampleModelTranslateY - minY + y;

    return new CairoSurface(sampleModel, this,
                      new Rectangle(x, y, width, height),
                      new Point(tcx, tcy));
  }
}
