diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java')
-rw-r--r-- | libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java new file mode 100644 index 000000000..71f6638e4 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java @@ -0,0 +1,428 @@ +/* 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)); + } +} |