aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java')
-rw-r--r--gcc-4.4.3/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java785
1 files changed, 785 insertions, 0 deletions
diff --git a/gcc-4.4.3/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/gcc-4.4.3/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
new file mode 100644
index 000000000..9b026953d
--- /dev/null
+++ b/gcc-4.4.3/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
@@ -0,0 +1,785 @@
+/* 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;
+
+import gnu.classpath.Configuration;
+import gnu.classpath.Pointer;
+
+public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
+{
+ static
+ {
+ if (true) // GCJ LOCAL
+ {
+ 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;
+
+ /**
+ * The pointer to the native pixbuf loader.
+ *
+ * This field is manipulated by native code. Don't change or remove
+ * without adjusting the native code.
+ */
+ private Pointer nativeDecoder;
+
+ // 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<String> mimeTypes = new ArrayList<String>();
+ public ArrayList<String> extensions = new ArrayList<String>();
+
+ 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<ImageFormatSpec> imageFormatSpecs;
+
+ public static ImageFormatSpec registerFormat(String name, boolean writable)
+ {
+ ImageFormatSpec ifs = new ImageFormatSpec(name, writable);
+ synchronized(GdkPixbufDecoder.class)
+ {
+ if (imageFormatSpecs == null)
+ imageFormatSpecs = new ArrayList<ImageFormatSpec>();
+ imageFormatSpecs.add(ifs);
+ }
+ return ifs;
+ }
+
+ static String[] getFormatNames(boolean writable)
+ {
+ ArrayList<String> names = new ArrayList<String>();
+ synchronized (imageFormatSpecs)
+ {
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = 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<String> j = ifs.extensions.iterator();
+ while (j.hasNext())
+ names.add(j.next());
+ }
+ }
+ return names.toArray(new String[names.size()]);
+ }
+
+ static String[] getFormatExtensions(boolean writable)
+ {
+ ArrayList<String> extensions = new ArrayList<String>();
+ synchronized (imageFormatSpecs)
+ {
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = i.next();
+ if (writable && !ifs.writable)
+ continue;
+ Iterator<String> j = ifs.extensions.iterator();
+ while (j.hasNext())
+ extensions.add(j.next());
+ }
+ }
+ return extensions.toArray(new String[extensions.size()]);
+ }
+
+ static String[] getFormatMimeTypes(boolean writable)
+ {
+ ArrayList<String> mimeTypes = new ArrayList<String>();
+ synchronized (imageFormatSpecs)
+ {
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = i.next();
+ if (writable && !ifs.writable)
+ continue;
+ Iterator<String> j = ifs.mimeTypes.iterator();
+ while (j.hasNext())
+ mimeTypes.add(j.next());
+ }
+ }
+ return mimeTypes.toArray(new String[mimeTypes.size()]);
+ }
+
+
+ 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<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = i.next();
+
+ if (needWritable && !ifs.writable)
+ continue;
+
+ if (ifs.name.equals(str))
+ return str;
+
+ Iterator<String> j = ifs.extensions.iterator();
+ while (j.hasNext())
+ {
+ String extension = j.next();
+ if (extension.equals(str))
+ return ifs.name;
+ }
+
+ j = ifs.mimeTypes.iterator();
+ while (j.hasNext())
+ {
+ String mimeType = 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<Object> data = new ArrayList<Object>();
+
+ /**
+ * 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<ImageTypeSpecifier> getImageTypes(int imageIndex)
+ throws IOException
+ {
+ BufferedImage img = getBufferedImage();
+ Vector<ImageTypeSpecifier> vec = new Vector<ImageTypeSpecifier>();
+ 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 ();
+ }
+ }
+}