/* GdkPixbufDecoder.java -- Image data decoding object
   Copyright (C) 2003, 2004, 2005, 2006  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 java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import java.util.Vector;

import javax.imageio.IIOImage;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
{
  static 
  {
    System.loadLibrary("gtkpeer");

    initStaticState ();
  }
  
  /**
   * Lock that should be held for all gdkpixbuf operations. We don't use
   * the global gdk_threads_enter/leave functions since gdkpixbuf
   * operations can be done in parallel to drawing and manipulating gtk
   * widgets.
   */
  static Object pixbufLock = new Object();

  static native void initStaticState();
  private final int native_state = GtkGenericPeer.getUniqueInteger ();

  // initState() has been called, but pumpDone() has not yet been called.
  private boolean needsClose = false;

  // the current set of ImageConsumers for this decoder
  Vector curr;

  // interface to GdkPixbuf
  // These native functions should be called with the pixbufLock held.
  native void initState ();
  native void pumpBytes (byte[] bytes, int len) throws IOException;
  native void pumpDone () throws IOException;
  native void finish (boolean needsClose);

  /**
   * Converts given image to bytes.
   * Will call the GdkPixbufWriter for each chunk.
   */
  static native void streamImage(int[] bytes, String format,
                                 int width, int height,
                                 boolean hasAlpha, GdkPixbufWriter writer);

  // gdk-pixbuf provids data in RGBA format
  static final ColorModel cm = new DirectColorModel (32, 0xff000000, 
                                                     0x00ff0000, 
                                                     0x0000ff00, 
                                                     0x000000ff);
  public GdkPixbufDecoder (DataInput datainput)
  {
    super (datainput);
  }

  public GdkPixbufDecoder (InputStream in)
  {
    super (in);
  }

  public GdkPixbufDecoder (String filename)
  {
    super (filename);
  }
  
  public GdkPixbufDecoder (URL url)
  {
    super (url);
  }

  public GdkPixbufDecoder (byte[] imagedata, int imageoffset, int imagelength)
  {
    super (imagedata, imageoffset, imagelength);
  }

  // called back by native side: area_prepared_cb
  void areaPrepared (int width, int height)
  {

    if (curr == null)
      return;

    for (int i = 0; i < curr.size (); i++)
      {
        ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
        ic.setDimensions (width, height);
        ic.setColorModel (cm);
        ic.setHints (ImageConsumer.RANDOMPIXELORDER);
      }
  }
  
  // called back by native side: area_updated_cb
  void areaUpdated (int x, int y, int width, int height, 
                    int pixels[], int scansize)
  {
    if (curr == null)
      return;
    
    for (int i = 0; i < curr.size (); i++)
      {
        ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
        ic.setPixels (x, y, width, height, cm, pixels, 0, scansize);
      }
  }
  
  // called from an async image loader of one sort or another, this method
  // repeatedly reads bytes from the input stream and passes them through a
  // GdkPixbufLoader using the native method pumpBytes. pumpBytes in turn
  // decodes the image data and calls back areaPrepared and areaUpdated on
  // this object, feeding back decoded pixel blocks, which we pass to each
  // of the ImageConsumers in the provided Vector.

  public void produce (Vector v, InputStream is) throws IOException
  {
    curr = v;

    byte bytes[] = new byte[4096];
    int len = 0;
    synchronized(pixbufLock)
      {
	initState();
      }
    needsClose = true;

    // Note: We don't want the pixbufLock while reading from the InputStream.
    while ((len = is.read (bytes)) != -1)
      {
	synchronized(pixbufLock)
	  {
	    pumpBytes (bytes, len);
	  }
      }

    synchronized(pixbufLock)
      {
	pumpDone();
      }

    needsClose = false;
    
    for (int i = 0; i < curr.size (); i++)
      {
        ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
        ic.imageComplete (ImageConsumer.STATICIMAGEDONE);
      }

    curr = null;
  }

  public void finalize()
  {
    synchronized(pixbufLock)
      {
	finish(needsClose);
      }
  }


  public static class ImageFormatSpec
  {
    public String name;
    public boolean writable = false;    
    public ArrayList mimeTypes = new ArrayList();
    public ArrayList extensions = new ArrayList();

    public ImageFormatSpec(String name, boolean writable)
    {
      this.name = name;
      this.writable = writable;
    }

    public synchronized void addMimeType(String m)
    {
      mimeTypes.add(m);
    }

    public synchronized void addExtension(String e)
    {
      extensions.add(e);
    }    
  }

  static ArrayList imageFormatSpecs;

  public static ImageFormatSpec registerFormat(String name, boolean writable) 
  {
    ImageFormatSpec ifs = new ImageFormatSpec(name, writable);
    synchronized(GdkPixbufDecoder.class)
      {
        if (imageFormatSpecs == null)
          imageFormatSpecs = new ArrayList();
        imageFormatSpecs.add(ifs);
      }
    return ifs;
  }

  static String[] getFormatNames(boolean writable)
  {
    ArrayList names = new ArrayList();
    synchronized (imageFormatSpecs) 
      {
        Iterator i = imageFormatSpecs.iterator();
        while (i.hasNext())
          {
            ImageFormatSpec ifs = (ImageFormatSpec) i.next();
            if (writable && !ifs.writable)
              continue;
            names.add(ifs.name);

            /* 
             * In order to make the filtering code work, we need to register
             * this type under every "format name" likely to be used as a synonym.
             * This generally means "all the extensions people might use". 
             */

            Iterator j = ifs.extensions.iterator();
            while (j.hasNext())
              names.add((String) j.next());
          }
      }
    Object[] objs = names.toArray();
    String[] strings = new String[objs.length];
    for (int i = 0; i < objs.length; ++i)
      strings[i] = (String) objs[i];
    return strings;
  }

  static String[] getFormatExtensions(boolean writable)
  {
    ArrayList extensions = new ArrayList();
    synchronized (imageFormatSpecs) 
      {
        Iterator i = imageFormatSpecs.iterator();
        while (i.hasNext())
          {
            ImageFormatSpec ifs = (ImageFormatSpec) i.next();
            if (writable && !ifs.writable)
              continue;
            Iterator j = ifs.extensions.iterator();
            while (j.hasNext())
              extensions.add((String) j.next());
          }
      }
    Object[] objs = extensions.toArray();
    String[] strings = new String[objs.length];
    for (int i = 0; i < objs.length; ++i)
      strings[i] = (String) objs[i];
    return strings;
  }

  static String[] getFormatMimeTypes(boolean writable)
  {
    ArrayList mimeTypes = new ArrayList();
    synchronized (imageFormatSpecs) 
      {
        Iterator i = imageFormatSpecs.iterator();
        while (i.hasNext())
          {
            ImageFormatSpec ifs = (ImageFormatSpec) i.next();
            if (writable && !ifs.writable)
              continue;
            Iterator j = ifs.mimeTypes.iterator();
            while (j.hasNext())
              mimeTypes.add((String) j.next());
          }
      }
    Object[] objs = mimeTypes.toArray();
    String[] strings = new String[objs.length];
    for (int i = 0; i < objs.length; ++i)
      strings[i] = (String) objs[i];
    return strings;
  }

  
  static String findFormatName(Object ext, boolean needWritable)
  {
    if (ext == null)
      return null;

    if (!(ext instanceof String))
      throw new IllegalArgumentException("extension is not a string");

    String str = (String) ext;

    Iterator i = imageFormatSpecs.iterator();
    while (i.hasNext())
      {
        ImageFormatSpec ifs = (ImageFormatSpec) i.next();

        if (needWritable && !ifs.writable)
          continue;

        if (ifs.name.equals(str))
          return str;

        Iterator j = ifs.extensions.iterator(); 
        while (j.hasNext())
          {
            String extension = (String)j.next();
            if (extension.equals(str))
              return ifs.name;
          }

        j = ifs.mimeTypes.iterator(); 
        while (j.hasNext())
          {
            String mimeType = (String)j.next();
            if (mimeType.equals(str))
              return ifs.name;
          }
      }      
    throw new IllegalArgumentException("unknown extension '" + str + "'");
  }

  private static GdkPixbufReaderSpi readerSpi;
  private static GdkPixbufWriterSpi writerSpi;

  public static synchronized GdkPixbufReaderSpi getReaderSpi()
  {
    if (readerSpi == null)
      readerSpi = new GdkPixbufReaderSpi();
    return readerSpi;
  }

  public static synchronized GdkPixbufWriterSpi getWriterSpi()
  {
    if (writerSpi == null)
      writerSpi = new GdkPixbufWriterSpi();
    return writerSpi;
  }

  public static void registerSpis(IIORegistry reg) 
  {
    reg.registerServiceProvider(getReaderSpi(), ImageReaderSpi.class);
    reg.registerServiceProvider(getWriterSpi(), ImageWriterSpi.class);
  }

  public static class GdkPixbufWriterSpi extends ImageWriterSpi
  {
    public GdkPixbufWriterSpi() 
    {      
      super("GdkPixbuf", "2.x",
            GdkPixbufDecoder.getFormatNames(true), 
            GdkPixbufDecoder.getFormatExtensions(true), 
            GdkPixbufDecoder.getFormatMimeTypes(true),
            "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriter",
            new Class[] { ImageOutputStream.class },
            new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReaderSpi" },
            false, null, null, null, null,
            false, null, null, null, null);
    }

    public boolean canEncodeImage(ImageTypeSpecifier ts)
    {
      return true;
    }

    public ImageWriter createWriterInstance(Object ext)
    {
      return new GdkPixbufWriter(this, ext);
    }

    public String getDescription(java.util.Locale loc)
    {
      return "GdkPixbuf Writer SPI";
    }

  }

  public static class GdkPixbufReaderSpi extends ImageReaderSpi
  {
    public GdkPixbufReaderSpi() 
    { 
      super("GdkPixbuf", "2.x",
            GdkPixbufDecoder.getFormatNames(false), 
            GdkPixbufDecoder.getFormatExtensions(false), 
            GdkPixbufDecoder.getFormatMimeTypes(false),
            "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReader",
            new Class[] { ImageInputStream.class },
            new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriterSpi" },
            false, null, null, null, null,
            false, null, null, null, null);
    }

    public boolean canDecodeInput(Object obj) 
    { 
      return true; 
    }

    public ImageReader createReaderInstance(Object ext)
    {
      return new GdkPixbufReader(this, ext);
    }

    public String getDescription(Locale loc)
    {
      return "GdkPixbuf Reader SPI";
    }
  }

  private static class GdkPixbufWriter
    extends ImageWriter implements Runnable
  {
    String ext;
    public GdkPixbufWriter(GdkPixbufWriterSpi ownerSpi, Object ext)
    {
      super(ownerSpi);
      this.ext = findFormatName(ext, true);
    }

    public IIOMetadata convertImageMetadata (IIOMetadata inData,
                                             ImageTypeSpecifier imageType,
                                             ImageWriteParam param)
    {
      return null;
    }

    public IIOMetadata convertStreamMetadata (IIOMetadata inData,
                                              ImageWriteParam param)
    {
      return null;
    }

    public IIOMetadata getDefaultImageMetadata (ImageTypeSpecifier imageType, 
                                                ImageWriteParam param)
    {
      return null;
    }

    public IIOMetadata getDefaultStreamMetadata (ImageWriteParam param)
    {
      return null;
    }

  public void write (IIOMetadata streamMetadata, IIOImage i, ImageWriteParam param)
    throws IOException
    {
      RenderedImage image = i.getRenderedImage();
      Raster ras = image.getData();
      int width = ras.getWidth();
      int height = ras.getHeight();
      ColorModel model = image.getColorModel();
      int[] pixels = CairoGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras);
      
      if (pixels == null)
        {
	  BufferedImage img;
	  if(model != null && model.hasAlpha())
	    img = CairoSurface.getBufferedImage(width, height);
	  img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
          int[] pix = new int[4];
          for (int y = 0; y < height; ++y)
            for (int x = 0; x < width; ++x)
              img.setRGB(x, y, model.getRGB(ras.getPixel(x, y, pix)));
          pixels = CairoGraphics2D.findSimpleIntegerArray (img.getColorModel(), 
                                                         img.getRaster());
          model = img.getColorModel();
        }

      Thread workerThread = new Thread(this, "GdkPixbufWriter");
      workerThread.start();
      processImageStarted(1);
      synchronized(pixbufLock)
	{
	  streamImage(pixels, this.ext, width, height, model.hasAlpha(), 
		      this);
	}
      synchronized(data)
        {
          data.add(DATADONE);
          data.notifyAll();
        }

      while (workerThread.isAlive())
        {
	  try
	    {
	      workerThread.join();
	    }
	  catch (InterruptedException ioe)
	    {
	      // Ignored.
	    }
        }

      if (exception != null)
	throw exception;

      processImageComplete();
    }    

    /**
     * Object marking end of data from native streamImage code.
     */
    private static final Object DATADONE = new Object();

    /**
     * Holds the data gotten from the native streamImage code.
     * A worker thread will pull data out.
     * Needs to be synchronized for access.
     * The special object DATADONE is added when all data has been delivered.
     */
    private ArrayList data = new ArrayList();

    /**
     * Holds any IOException thrown by the run method that needs
     * to be rethrown by the write method.
     */
    private IOException exception;

    /** Callback for streamImage native code. **/
    private void write(byte[] bs)
    {
      synchronized(data)
        {
          data.add(bs);
          data.notifyAll();
        }
    }

    public void run()
    {
      boolean done = false;
      while (!done)
        {
          synchronized(data)
            {
              while (data.isEmpty())
                {
                  try
                    {
                      data.wait();
                    }
                  catch (InterruptedException ie)
                    {
                      /* ignore */
                    }
                }

              Object o = data.remove(0);
              if (o == DATADONE)
                done = true;
              else
                {
                  DataOutput out = (DataOutput) getOutput();
                  try
                    {
                      out.write((byte[]) o);
                    }
                  catch (IOException ioe)
                    {
                      // We are only interested in the first exception.
                      if (exception == null)
                        exception = ioe;
                    }
                }
            }
        }
    }
  }

  private static class GdkPixbufReader 
    extends ImageReader
    implements ImageConsumer
  {
    // ImageConsumer parts
    GdkPixbufDecoder dec;
    BufferedImage bufferedImage;
    ColorModel defaultModel;
    int width;
    int height;
    String ext;
    
    public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext)
    {
      super(ownerSpi);
      this.ext = findFormatName(ext, false);
    }

    public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext, GdkPixbufDecoder d)
    {
      this(ownerSpi, ext);
      dec = d;
    }

    public void setDimensions(int w, int h)
    {
      processImageStarted(1);
      width = w;
      height = h;
    }
    
    public void setProperties(Hashtable props) {}

    public void setColorModel(ColorModel model) 
    {
      defaultModel = model;
    }

    public void setHints(int flags) {}

    public void setPixels(int x, int y, int w, int h, 
                          ColorModel model, byte[] pixels, 
                          int offset, int scansize)
    {
    }      

    public void setPixels(int x, int y, int w, int h, 
                          ColorModel model, int[] pixels, 
                          int offset, int scansize)
    {
      if (model == null)
        model = defaultModel;
      
      if (bufferedImage == null)
        {
	  if(model != null && model.hasAlpha())
	    bufferedImage = new BufferedImage (width, height, BufferedImage.TYPE_INT_ARGB);
	  else
	    bufferedImage = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB);
        }

      int pixels2[];
      if (model != null)
        {
          pixels2 = new int[pixels.length];
          for (int yy = 0; yy < h; yy++)
            for (int xx = 0; xx < w; xx++)
              {
                int i = yy * scansize + xx;
                pixels2[i] = model.getRGB (pixels[i]);
              }
        }
      else
        pixels2 = pixels;

      bufferedImage.setRGB (x, y, w, h, pixels2, offset, scansize);
      processImageProgress(y / (height == 0 ? 1 : height));
    }

    public void imageComplete(int status) 
    {
      processImageComplete();
    }

    public BufferedImage getBufferedImage()
    {
      if (bufferedImage == null && dec != null)
        dec.startProduction (this);
      return bufferedImage;
    }

    // ImageReader parts

    public int getNumImages(boolean allowSearch)
      throws IOException
    {
      return 1;
    }

    public IIOMetadata getImageMetadata(int i) 
    {
      return null;
    }

    public IIOMetadata getStreamMetadata()
      throws IOException
    {
      return null;
    }

    public Iterator getImageTypes(int imageIndex)
      throws IOException
    {
      BufferedImage img = getBufferedImage();
      Vector vec = new Vector();
      vec.add(new ImageTypeSpecifier(img));
      return vec.iterator();
    }
    
    public int getHeight(int imageIndex)
      throws IOException
    {
      return getBufferedImage().getHeight();
    }

    public int getWidth(int imageIndex)
      throws IOException
    {
      return getBufferedImage().getWidth();
    }

    public void setInput(Object input,
                         boolean seekForwardOnly,
                         boolean ignoreMetadata)
    {
      super.setInput(input, seekForwardOnly, ignoreMetadata);
      Object get = getInput();
      if (get instanceof InputStream)
        dec = new GdkPixbufDecoder((InputStream) get);
      else if (get instanceof DataInput)
        dec = new GdkPixbufDecoder((DataInput) get);
      else
	throw new IllegalArgumentException("input object not supported: "
					   + get);
    }

    public BufferedImage read(int imageIndex, ImageReadParam param)
      throws IOException
    {
      return getBufferedImage ();
    }
  }
}
