diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
commit | f911ba985aa7fe0096c386c5be385ac5825ea527 (patch) | |
tree | a0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/gnu/java/awt | |
parent | 6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff) | |
download | gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.zip gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.bz2 |
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/gnu/java/awt')
80 files changed, 16248 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/awt/AWTUtilities.java b/libjava/classpath/gnu/java/awt/AWTUtilities.java new file mode 100644 index 0000000..a02d1c4 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/AWTUtilities.java @@ -0,0 +1,321 @@ +/* AWTUtilities.java -- Common utility methods for AWT and Swing. + Copyright (C) 2005 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; + +import java.awt.Component; +import java.awt.Container; +import java.util.AbstractSequentialList; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.WeakHashMap; + +/** + * This class provides utility methods that are commonly used in AWT + * (and Swing). + */ +public class AWTUtilities +{ + + /** + * This List implementation wraps the Component[] returned by + * {@link Container#getComponents()} and iterates over the visible Components + * in that array. This class is used in {@link #getVisibleChildren}. + */ + static class VisibleComponentList extends AbstractSequentialList + { + /** + * The ListIterator for this List. + */ + class VisibleComponentIterator implements ListIterator + { + /** The current index in the Component[]. */ + int index; + + /** The index in the List of visible Components. */ + int listIndex; + + /** + * Creates a new VisibleComponentIterator that starts at the specified + * <code>listIndex</code>. The array of Components is searched from + * the beginning to find the matching array index. + * + * @param listIndex the index from where to begin iterating + */ + VisibleComponentIterator(int listIndex) + { + this.listIndex = listIndex; + int visibleComponentsFound = 0; + for (index = 0; visibleComponentsFound != listIndex; index++) + { + if (components[index].isVisible()) + visibleComponentsFound++; + } + } + + /** + * Returns <code>true</code> if there are more visible components in the + * array, <code>false</code> otherwise. + * + * @return <code>true</code> if there are more visible components in the + * array, <code>false</code> otherwise + */ + public boolean hasNext() + { + boolean hasNext = false; + for (int i = index; i < components.length; i++) + { + if (components[i].isVisible()) + { + hasNext = true; + break; + } + } + return hasNext; + } + + /** + * Returns the next visible <code>Component</code> in the List. + * + * @return the next visible <code>Component</code> in the List + * + * @throws if there is no next element + */ + public Object next() + { + Object o = null; + for (; index < components.length; index++) + { + if (components[index].isVisible()) + { + o = components[index]; + break; + } + } + if (o != null) + { + index++; + listIndex++; + return o; + } + else + throw new NoSuchElementException(); + } + + /** + * Returns <code>true</code> if there are more visible components in the + * array in the reverse direction, <code>false</code> otherwise. + * + * @return <code>true</code> if there are more visible components in the + * array in the reverse direction, <code>false</code> otherwise + */ + public boolean hasPrevious() + { + boolean hasPrevious = false; + for (int i = index - 1; i >= 0; i--) + { + if (components[i].isVisible()) + { + hasPrevious = true; + break; + } + } + return hasPrevious; + } + + /** + * Returns the previous visible <code>Component</code> in the List. + * + * @return the previous visible <code>Component</code> in the List + * + * @throws NoSuchElementException if there is no previous element + */ + public Object previous() + { + Object o = null; + for (index--; index >= 0; index--) + { + if (components[index].isVisible()) + { + o = components[index]; + break; + } + } + if (o != null) + { + listIndex--; + return o; + } + else + throw new NoSuchElementException(); + } + + /** + * Returns the index of the next element in the List. + * + * @return the index of the next element in the List + */ + public int nextIndex() + { + return listIndex + 1; + } + + /** + * Returns the index of the previous element in the List. + * + * @return the index of the previous element in the List + */ + public int previousIndex() + { + return listIndex - 1; + } + + /** + * This operation is not supported because the List is immutable. + * + * @throws UnsupportedOperationException because the List is immutable + */ + public void remove() + { + throw new UnsupportedOperationException + ("VisibleComponentList is immutable"); + } + + /** + * This operation is not supported because the List is immutable. + * + * @param o not used here + * + * @throws UnsupportedOperationException because the List is immutable + */ + public void set(Object o) + { + throw new UnsupportedOperationException + ("VisibleComponentList is immutable"); + } + + /** + * This operation is not supported because the List is immutable. + * + * @param o not used here + * + * @throws UnsupportedOperationException because the List is immutable + */ + public void add(Object o) + { + throw new UnsupportedOperationException + ("VisibleComponentList is immutable"); + } + } + + /** + * The components over which we iterate. Only the visible components + * are returned by this List. + */ + Component[] components; + + /** + * Creates a new instance of VisibleComponentList that wraps the specified + * <code>Component[]</code>. + * + * @param c the <code>Component[]</code> to be wrapped. + */ + VisibleComponentList(Component[] c) + { + components = c; + } + + /** + * Returns a {@link ListIterator} for iterating over this List. + * + * @return a {@link ListIterator} for iterating over this List + */ + public ListIterator listIterator(int index) + { + return new VisibleComponentIterator(index); + } + + /** + * Returns the number of visible components in the wrapped Component[]. + * + * @return the number of visible components + */ + public int size() + { + int visibleComponents = 0; + for (int i = 0; i < components.length; i++) + if (components[i].isVisible()) + visibleComponents++; + return visibleComponents; + } + } + + /** + * The cache for our List instances. We try to hold one instance of + * VisibleComponentList for each Component[] that is requested. Note + * that we use a WeakHashMap for caching, so that the cache itself + * does not keep the array or the List from beeing garbage collected + * if no other objects hold references to it. + */ + static WeakHashMap visibleChildrenCache = new WeakHashMap(); + + /** + * Returns the visible children of a {@link Container}. This method is + * commonly needed in LayoutManagers, because they only have to layout + * the visible children of a Container. + * + * @param c the Container from which to extract the visible children + * + * @return the visible children of <code>c</code> + */ + public static List getVisibleChildren(Container c) + { + Component[] children = c.getComponents(); + Object o = visibleChildrenCache.get(children); + VisibleComponentList visibleChildren = null; + if (o == null) + { + visibleChildren = new VisibleComponentList(children); + visibleChildrenCache.put(children, visibleChildren); + } + else + visibleChildren = (VisibleComponentList) o; + + return visibleChildren; + } +} diff --git a/libjava/classpath/gnu/java/awt/BitMaskExtent.java b/libjava/classpath/gnu/java/awt/BitMaskExtent.java new file mode 100644 index 0000000..2813499 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/BitMaskExtent.java @@ -0,0 +1,79 @@ +/* Copyright (C) 2000, 2002 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 gnu.java.awt; + +/** + * Simple transparent utility class that can be used to perform bit + * mask extent calculations. + */ +public final class BitMaskExtent +{ + /** The number of the least significant bit of the bit mask extent. */ + public byte leastSignificantBit; + + /** The number of bits in the bit mask extent. */ + public byte bitWidth; + + /** + * Set the bit mask. This will calculate and set the leastSignificantBit + * and bitWidth fields. + * + * @see #leastSignificantBit + * @see #bitWidth + */ + public void setMask(long mask) + { + leastSignificantBit = 0; + bitWidth = 0; + if (mask == 0) return; + long shiftMask = mask; + for (; (shiftMask&1) == 0; shiftMask >>>=1) leastSignificantBit++; + for (; (shiftMask&1) != 0; shiftMask >>>=1) bitWidth++; + + if (shiftMask != 0) + throw new IllegalArgumentException("mask must be continuous"); + } + + /** + * Calculate the bit mask based on the values of the + * leastSignificantBit and bitWidth fields. + */ + public long toMask() + { + return ((1<<bitWidth)-1) << leastSignificantBit; + } +} diff --git a/libjava/classpath/gnu/java/awt/BitwiseXORComposite.java b/libjava/classpath/gnu/java/awt/BitwiseXORComposite.java new file mode 100644 index 0000000..b568e11 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/BitwiseXORComposite.java @@ -0,0 +1,295 @@ +/* BitwiseXORComposite.java -- Composite for emulating old-style XOR. + Copyright (C) 2003, 2004 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; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.CompositeContext; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + + +/** + * A composite for emulating traditional bitwise XOR of pixel values. + * Please note that this composite does <i>not</i> implement the Porter-Duff + * XOR operator, but an exclusive or of overlapping subpixel regions. + * + * <p><img src="doc-files/BitwiseXORComposite-1.png" width="545" + * height="138" alt="A screen shot of BitwiseXORComposite in action" + * /> + * + * <p>The above screen shot shows the result of applying six different + * BitwiseXORComposites. They were constructed with the colors colors + * white, blue, black, orange, green, and brown, respectively. Each + * composite was used to paint a fully white rectangle on top of the + * blue bar in the background. + * + * <p>The purpose of this composite is to support the {@link + * Graphics#setXORMode(Color)} method in composite-aware graphics + * implementations. Applications typically would use + * <code>setXORMode</code> for drawing “highlights” such + * as text selections or cursors by inverting colors temporarily and + * then inverting them back. + * + * <p>A concrete <code>Graphics</code> implementation may contain + * the following code: + * + * <p><pre> public void setXORMode(Color xorColor) + * { + * setComposite(new gnu.java.awt.BitwiseXORComposite(xorColor)); + * } + * + * public void setPaintMode() + * { + * setComposite(java.awt.AlphaComposite.SrcOver); + * }</pre> + * + * @author Graydon Hoare (graydon@redhat.com) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BitwiseXORComposite + implements Composite +{ + /** + * The color whose RGB value is xor-ed with the values of each + * pixel. + */ + protected Color xorColor; + + + /** + * Constructs a new composite for xor-ing the pixel value. + * + * @param xorColor the color whose pixel value will be bitwise + * xor-ed with the source and destination pixels. + */ + public BitwiseXORComposite(Color xorColor) + { + this.xorColor = xorColor; + } + + + /** + * Creates a context object for performing the compositing + * operation. Several contexts may co-exist for one composite; each + * context may simultaneously be called from concurrent threads. + * + * @param srcColorModel the color model of the source. + * @param dstColorModel the color model of the destination. + * @param hints hints for choosing between rendering alternatives. + */ + public CompositeContext createContext(ColorModel srcColorModel, + ColorModel dstColorModel, + RenderingHints hints) + { + if (IntContext.isSupported(srcColorModel, dstColorModel, hints)) + return new IntContext(srcColorModel, xorColor); + + return new GeneralContext(srcColorModel, dstColorModel, xorColor); + } + + + /** + * A fallback CompositeContext that performs bitwise XOR of pixel + * values with the pixel value of the specified <code>xorColor</code>. + * + * <p>Applying this CompositeContext on a 1024x1024 BufferedImage of + * <code>TYPE_INT_RGB</code> took 611 ms on a lightly loaded 2.4 GHz + * Intel Pentium 4 CPU running Sun J2SE 1.4.1_01 on GNU/Linux + * 2.4.20. The timing is the average of ten runs on the same + * BufferedImage. Since the measurements were taken with {@link + * System#currentTimeMillis()}, they are rather inaccurate. + * + * @author Graydon Hoare (graydon@redhat.com) + */ + private static class GeneralContext + implements CompositeContext + { + ColorModel srcColorModel; + ColorModel dstColorModel; + Color xorColor; + + public GeneralContext(ColorModel srcColorModel, + ColorModel dstColorModel, + Color xorColor) + { + this.srcColorModel = srcColorModel; + this.dstColorModel = dstColorModel; + this.xorColor = xorColor; + } + + + public void compose(Raster src, Raster dstIn, WritableRaster dstOut) + { + Rectangle srcRect = src.getBounds(); + Rectangle dstInRect = dstIn.getBounds(); + Rectangle dstOutRect = dstOut.getBounds(); + + int xp = xorColor.getRGB(); + int w = Math.min(Math.min(srcRect.width, dstOutRect.width), + dstInRect.width); + int h = Math.min(Math.min(srcRect.height, dstOutRect.height), + dstInRect.height); + + Object srcPix = null, dstPix = null, rpPix = null; + + // Re-using the rpPix object saved 1-2% of execution time in + // the 1024x1024 pixel benchmark. + + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++) + { + srcPix = src.getDataElements(x + srcRect.x, y + srcRect.y, srcPix); + dstPix = dstIn.getDataElements(x + dstInRect.x, y + dstInRect.y, + dstPix); + int sp = srcColorModel.getRGB(srcPix); + int dp = dstColorModel.getRGB(dstPix); + int rp = sp ^ xp ^ dp; + dstOut.setDataElements(x + dstOutRect.x, y + dstOutRect.y, + dstColorModel.getDataElements(rp, rpPix)); + } + } + } + + + /** + * Disposes any cached resources. The default implementation does + * nothing because no resources are cached. + */ + public void dispose() + { + } + } + + + /** + * An optimized CompositeContext that performs bitwise XOR of + * <code>int</code> pixel values with the pixel value of a specified + * <code>xorColor</code>. This CompositeContext working only for + * rasters whose transfer format is {@link DataBuffer#TYPE_INT}. + * + * <p>Applying this CompositeContext on a 1024x1024 BufferedImage of + * <code>TYPE_INT_RGB</code> took 69 ms on a lightly loaded 2.4 GHz + * Intel Pentium 4 CPU running Sun J2SE 1.4.1_01 on GNU/Linux + * 2.4.20. The timing is the average of ten runs on the same + * BufferedImage. Since the measurements were taken with {@link + * System#currentTimeMillis()}, they are rather inaccurate. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + private static class IntContext + extends GeneralContext + { + public IntContext(ColorModel colorModel, Color xorColor) + { + super(colorModel, colorModel, xorColor); + } + + + public void compose(Raster src, Raster dstIn, + WritableRaster dstOut) + { + int aX, bX, dstX, aY, bY, dstY, width, height; + int xorPixel; + int[] srcLine, dstLine; + + aX = src.getMinX(); + aY = src.getMinY(); + bX = dstIn.getMinX(); + bY = dstIn.getMinY(); + dstX = dstOut.getMinX(); + dstY = dstOut.getMinY(); + width = Math.min(Math.min(src.getWidth(), dstIn.getWidth()), + dstOut.getWidth()); + height = Math.min(Math.min(src.getHeight(), dstIn.getHeight()), + dstOut.getHeight()); + if ((width < 1) || (height < 1)) + return; + + srcLine = new int[width]; + dstLine = new int[width]; + + /* We need an int[] array with at least one element here; + * srcLine is as good as any other. + */ + srcColorModel.getDataElements(this.xorColor.getRGB(), srcLine); + xorPixel = srcLine[0]; + + for (int y = 0; y < height; y++) + { + src.getDataElements(aX, y + aY, width, 1, srcLine); + dstIn.getDataElements(bX, y + bY, width, 1, dstLine); + + for (int x = 0; x < width; x++) + dstLine[x] ^= srcLine[x] ^ xorPixel; + + dstOut.setDataElements(dstX, y + dstY, width, 1, dstLine); + } + } + + + /** + * Determines whether an instance of this CompositeContext would + * be able to process the specified color models. + */ + public static boolean isSupported(ColorModel srcColorModel, + ColorModel dstColorModel, + RenderingHints hints) + { + // FIXME: It would be good if someone could review these checks. + // They probably need to be more restrictive. + + int transferType; + + transferType = srcColorModel.getTransferType(); + if (transferType != dstColorModel.getTransferType()) + return false; + + if (transferType != DataBuffer.TYPE_INT) + return false; + + return true; + } + } +} diff --git a/libjava/classpath/gnu/java/awt/Buffers.java b/libjava/classpath/gnu/java/awt/Buffers.java new file mode 100644 index 0000000..c6ccf91 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/Buffers.java @@ -0,0 +1,243 @@ +/* Buffers.java -- + Copyright (C) 2000, 2002, 2004 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 gnu.java.awt; + +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferDouble; +import java.awt.image.DataBufferFloat; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.DataBufferUShort; + +/** + * Utility class for creating and accessing data buffers of arbitrary + * data types. + */ +public final class Buffers +{ + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer. + * @param data an array containing data, or null + * @param size the size of the data buffer bank + */ + public static DataBuffer createBuffer(int dataType, Object data, + int size) + { + if (data == null) return createBuffer(dataType, size, 1); + + return createBufferFromData(dataType, data, size); + } + + + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer. + * @param size the size of the data buffer bank + */ + public static DataBuffer createBuffer(int dataType, int size) { + return createBuffer(dataType, size, 1); + } + + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer. + * @param size the size of the data buffer bank + * @param numBanks the number of banks the buffer should have + */ + public static DataBuffer createBuffer(int dataType, int size, int numBanks) + { + switch (dataType) + { + case DataBuffer.TYPE_BYTE: + return new DataBufferByte(size, numBanks); + case DataBuffer.TYPE_SHORT: + return new DataBufferShort(size, numBanks); + case DataBuffer.TYPE_USHORT: + return new DataBufferUShort(size, numBanks); + case DataBuffer.TYPE_INT: + return new DataBufferInt(size, numBanks); + case DataBuffer.TYPE_FLOAT: + return new DataBufferFloat(size, numBanks); + case DataBuffer.TYPE_DOUBLE: + return new DataBufferDouble(size, numBanks); + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Create a data buffer of a particular type. + * + * @param dataType the desired data type of the buffer + * @param data an array containing the data + * @param size the size of the data buffer bank + */ + public static DataBuffer createBufferFromData(int dataType, Object data, + int size) + { + switch (dataType) + { + case DataBuffer.TYPE_BYTE: + return new DataBufferByte((byte[]) data, size); + case DataBuffer.TYPE_SHORT: + return new DataBufferShort((short[]) data, size); + case DataBuffer.TYPE_USHORT: + return new DataBufferUShort((short[]) data, size); + case DataBuffer.TYPE_INT: + return new DataBufferInt((int[]) data, size); + case DataBuffer.TYPE_FLOAT: + return new DataBufferFloat((float[]) data, size); + case DataBuffer.TYPE_DOUBLE: + return new DataBufferDouble((double[]) data, size); + default: + throw new UnsupportedOperationException(); + } + } + + /** + * Return the data array of a data buffer, regardless of the data + * type. + * + * @return an array of primitive values. The actual array type + * depends on the data type of the buffer. + */ + public static Object getData(DataBuffer buffer) + { + if (buffer instanceof DataBufferByte) + return ((DataBufferByte) buffer).getData(); + + if (buffer instanceof DataBufferShort) + return ((DataBufferShort) buffer).getData(); + + if (buffer instanceof DataBufferUShort) + return ((DataBufferUShort) buffer).getData(); + + if (buffer instanceof DataBufferInt) + return ((DataBufferInt) buffer).getData(); + + if (buffer instanceof DataBufferFloat) + return ((DataBufferFloat) buffer).getData(); + + if (buffer instanceof DataBufferDouble) + return ((DataBufferDouble) buffer).getData(); + + throw new ClassCastException("Unknown data buffer type"); + } + + + /** + * Copy data from array contained in data buffer, much like + * System.arraycopy. Create a suitable destination array if the + * given destination array is null. + */ + public static Object getData(DataBuffer src, int srcOffset, + Object dest, int destOffset, + int length) + { + Object from; + if (src instanceof DataBufferByte) + { + from = ((DataBufferByte) src).getData(); + if (dest == null) dest = new byte[length+destOffset]; + } + else if (src instanceof DataBufferShort) + { + from = ((DataBufferShort) src).getData(); + if (dest == null) dest = new short[length+destOffset]; + } + else if (src instanceof DataBufferUShort) + { + from = ((DataBufferUShort) src).getData(); + if (dest == null) dest = new short[length+destOffset]; + } + else if (src instanceof DataBufferInt) + { + from = ((DataBufferInt) src).getData(); + if (dest == null) dest = new int[length+destOffset]; + } + else if (src instanceof DataBufferFloat) + { + from = ((DataBufferFloat) src).getData(); + if (dest == null) dest = new float[length+destOffset]; + } + else if (src instanceof DataBufferDouble) + { + from = ((DataBufferDouble) src).getData(); + if (dest == null) dest = new double[length+destOffset]; + } + else + { + throw new ClassCastException("Unknown data buffer type"); + } + + System.arraycopy(from, srcOffset, dest, destOffset, length); + return dest; + } + + /** + * @param bits the width of a data element measured in bits + * + * @return the smallest data type that can store data elements of + * the given number of bits, without any truncation. + */ + public static int smallestAppropriateTransferType(int bits) + { + if (bits <= 8) + { + return DataBuffer.TYPE_BYTE; + } + else if (bits <= 16) + { + return DataBuffer.TYPE_USHORT; + } + else if (bits <= 32) + { + return DataBuffer.TYPE_INT; + } + else + { + return DataBuffer.TYPE_UNDEFINED; + } + } +} diff --git a/libjava/classpath/gnu/java/awt/ClasspathToolkit.java b/libjava/classpath/gnu/java/awt/ClasspathToolkit.java new file mode 100644 index 0000000..5fb444f --- /dev/null +++ b/libjava/classpath/gnu/java/awt/ClasspathToolkit.java @@ -0,0 +1,379 @@ +/* ClasspathToolkit.java -- Abstract superclass for Classpath toolkits. + Copyright (C) 2003, 2004 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; + +import gnu.java.awt.EmbeddedWindow; +import gnu.java.awt.peer.ClasspathFontPeer; +import gnu.java.awt.peer.EmbeddedWindowPeer; +import gnu.java.awt.peer.ClasspathTextLayoutPeer; + +import java.awt.AWTException; +import java.awt.Dimension; +import java.awt.DisplayMode; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.font.FontRenderContext; +import java.awt.image.ColorModel; +import java.awt.image.ImageProducer; +import java.awt.peer.RobotPeer; +import java.io.File; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.AttributedString; +import java.util.HashMap; +import java.util.Map; + +import javax.imageio.spi.IIORegistry; + +/** + * An abstract superclass for Classpath toolkits. + * + * <p>There exist some parts of AWT and Java2D that are specific to + * the underlying platform, but for which the {@link Toolkit} class + * does not provide suitable abstractions. Examples include some + * methods of {@link Font} or {@link GraphicsEnvironment}. Those + * methods use ClasspathToolkit as a central place for obtaining + * platform-specific functionality. + * + * <p>In addition, ClasspathToolkit implements some abstract methods + * of {@link java.awt.Toolkit} that are not really platform-specific, + * such as the maintenance of a cache of loaded images. + * + * <p><b>Thread Safety:</b> The methods of this class may safely be + * called without external synchronization. This also hold for any + * inherited {@link Toolkit} methods. Subclasses are responsible for + * the necessary synchronization. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ClasspathToolkit + extends Toolkit +{ + /** + * A map from URLs to previously loaded images, used by {@link + * #getImage(java.net.URL)}. For images that were loaded via a path + * to an image file, the map contains a key with a file URL. + */ + private HashMap imageCache; + + + /** + * Returns a shared instance of the local, platform-specific + * graphics environment. + * + * <p>This method is specific to GNU Classpath. It gets called by + * the Classpath implementation of {@link + * GraphicsEnvironment.getLocalGraphcisEnvironment()}. + */ + public abstract GraphicsEnvironment getLocalGraphicsEnvironment(); + + + /** + * Determines the current size of the default, primary screen. + * + * @throws HeadlessException if the local graphics environment is + * headless, which means that no screen is attached and no user + * interaction is allowed. + */ + public Dimension getScreenSize() + { + DisplayMode mode; + + // getDefaultScreenDevice throws HeadlessException if the + // local graphics environment is headless. + mode = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDisplayMode(); + + return new Dimension(mode.getWidth(), mode.getHeight()); + } + + + /** + * Determines the current color model of the default, primary + * screen. + * + * @see GraphicsEnvironment#getDefaultScreenDevice() + * @see java.awt.GraphicsDevice#getDefaultConfiguration() + * @see java.awt.GraphicsConfiguration#getColorModel() + * + * @throws HeadlessException if the local graphics environment is + * headless, which means that no screen is attached and no user + * interaction is allowed. + */ + public ColorModel getColorModel() + { + // getDefaultScreenDevice throws HeadlessException if the + // local graphics environment is headless. + return GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration() + .getColorModel(); + } + + /** + * Retrieves the metrics for rendering a font on the screen. + * + * @param font the font whose metrics are requested. + */ + public FontMetrics getFontMetrics(Font font) + { + return ((ClasspathFontPeer) font.getPeer ()).getFontMetrics (font); + } + + + /** + * Acquires an appropriate {@link ClasspathFontPeer}, for use in + * classpath's implementation of {@link java.awt.Font}. + * + * @param name The logical name of the font. This may be either a face + * name or a logical font name, or may even be null. A default + * implementation of name decoding is provided in + * {@link ClasspathFontPeer}, but may be overridden in other toolkits. + * + * @param attrs Any extra {@link java.awt.font.TextAttribute} attributes + * this font peer should have, such as size, weight, family name, or + * transformation. + */ + public abstract ClasspathFontPeer getClasspathFontPeer (String name, Map attrs); + + public abstract ClasspathTextLayoutPeer + getClasspathTextLayoutPeer (AttributedString str, FontRenderContext frc); + + + /** + * Creates a {@link Font}, in a platform-specific manner. + * + * The default implementation simply constructs a {@link Font}, but some + * toolkits may wish to override this, to return {@link Font} subclasses which + * implement {@link java.awt.font.OpenType} or + * {@link java.awt.font.MultipleMaster}. + */ + public Font getFont (String name, Map attrs) + { + return new Font (name, attrs); + } + + + /** + * Creates a font, reading the glyph definitions from a stream. + * + * <p>This method provides the platform-specific implementation for + * the static factory method {@link Font#createFont(int, + * java.io.InputStream)}. + * + * @param format the format of the font data, such as {@link + * Font#TRUETYPE_FONT}. An implementation may ignore this argument + * if it is able to automatically recognize the font format from the + * provided data. + * + * @param stream an input stream from where the font data is read + * in. The stream will be advanced to the position after the font + * data, but not closed. + * + * @throws IllegalArgumentException if <code>format</code> is + * not supported. + * + * @throws FontFormatException if <code>stream</code> does not + * contain data in the expected format, or if required tables are + * missing from a font. + * + * @throws IOException if a problem occurs while reading in the + * contents of <code>stream</code>. + */ + public abstract Font createFont(int format, InputStream stream); + + + /** + * Returns an image from the specified file, which must be in a + * recognized format. The set of recognized image formats may vary + * from toolkit to toolkit. + * + * <p>This method maintains a cache for images. If an image has been + * loaded from the same path before, the cached copy will be + * returned. The implementation may hold cached copies for an + * indefinite time, which can consume substantial resources with + * large images. Users are therefore advised to use {@link + * #createImage(java.lang.String)} instead. + * + * <p>The default implementation creates a file URL for the + * specified path and invokes {@link #getImage(URL)}. + * + * @param path A path to the image file. + * + * @return IllegalArgumentException if <code>path</code> does not + * designate a valid path. + */ + public Image getImage(String path) + { + try + { + return getImage(new File(path).toURL()); + } + catch (MalformedURLException muex) + { + throw (IllegalArgumentException) new IllegalArgumentException(path) + .initCause(muex); + } + } + + + /** + * Loads an image from the specified URL. The image data must be in + * a recognized format. The set of recognized image formats may vary + * from toolkit to toolkit. + * + * <p>This method maintains a cache for images. If an image has been + * loaded from the same URL before, the cached copy will be + * returned. The implementation may hold cached copies for an + * indefinite time, which can consume substantial resources with + * large images. Users are therefore advised to use {@link + * #createImage(java.net.URL)} instead. + * + * @param url the URL from where the image is read. + */ + public Image getImage(URL url) + { + Image result; + + synchronized (this) + { + // Many applications never call getImage. Therefore, we lazily + // create the image cache when it is actually needed. + if (imageCache == null) + imageCache = new HashMap(); + else + { + result = (Image) imageCache.get(url); + if (result != null) + return result; + } + + // The createImage(URL) method, which is specified by + // java.awt.Toolkit, is not implemented by this abstract class + // because it is platform-dependent. Once Classpath has support + // for the javax.imageio package, it might be worth considering + // that toolkits provide native stream readers. Then, the class + // ClasspathToolkit could provide a general implementation that + // delegates the image format parsing to javax.imageio. + result = createImage(url); + + // It is not clear whether it would be a good idea to use weak + // references here. The advantage would be reduced memory + // consumption, since loaded images would not be kept + // forever. But on VMs that frequently perform garbage + // collection (which includes VMs with a parallel or incremental + // collector), the image might frequently need to be re-loaded, + // possibly over a slow network connection. + imageCache.put(url, result); + + return result; + } + } + + + /** + * Returns an image from the specified file, which must be in a + * recognized format. The set of recognized image formats may vary + * from toolkit to toolkit. + * + * <p>A new image is created every time this method gets called, + * even if the same path has been passed before. + * + * <p>The default implementation creates a file URL for the + * specified path and invokes {@link #createImage(URL)}. + * + * @param path A path to the file to be read in. + */ + public Image createImage(String path) + { + try + { + // The abstract method createImage(URL) is defined by + // java.awt.Toolkit, but intentionally not implemented by + // ClasspathToolkit because it is platform specific. + return createImage(new File(path).toURL()); + } + catch (MalformedURLException muex) + { + throw (IllegalArgumentException) new IllegalArgumentException(path) + .initCause(muex); + } + } + + /** + * Creates an ImageProducer from the specified URL. The image is assumed + * to be in a recognised format. If the toolkit does not implement the + * image format or the image format is not recognised, null is returned. + * This default implementation is overriden by the Toolkit implementations. + * + * @param url URL to read image data from. + */ + public ImageProducer createImageProducer(URL url) + { + return null; + } + + public abstract RobotPeer createRobot (GraphicsDevice screen) + throws AWTException; + + /** + * Creates an embedded window peer, and associates it with an + * EmbeddedWindow object. + * + * @param w The embedded window with which to associate a peer. + */ + public abstract EmbeddedWindowPeer createEmbeddedWindow (EmbeddedWindow w); + + /** + * Used to register ImageIO SPIs provided by the toolkit. + */ + + public void registerImageIOSpis(IIORegistry reg) + { + } + + public abstract boolean nativeQueueEmpty(); + public abstract void wakeNativeQueue(); + public abstract void iterateNativeQueue(EventQueue locked, boolean block); +} diff --git a/libjava/classpath/gnu/java/awt/ComponentDataBlitOp.java b/libjava/classpath/gnu/java/awt/ComponentDataBlitOp.java new file mode 100644 index 0000000..545427e --- /dev/null +++ b/libjava/classpath/gnu/java/awt/ComponentDataBlitOp.java @@ -0,0 +1,156 @@ +/* Copyright (C) 2000, 2002, 2004 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 gnu.java.awt; + +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.ComponentSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.RasterOp; +import java.awt.image.WritableRaster; + +/** + * This raster copy operation assumes that both source and destination + * sample models are tightly pixel packed and contain the same number + * of bands. + * + * @throws java.lang.ClassCastException if the sample models of the + * rasters are not of type ComponentSampleModel. + * + * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) + */ +public class ComponentDataBlitOp implements RasterOp +{ + public static final ComponentDataBlitOp INSTANCE = new ComponentDataBlitOp(); + + public WritableRaster filter(Raster src, WritableRaster dest) + { + if (dest == null) + dest = createCompatibleDestRaster(src); + + DataBuffer srcDB = src.getDataBuffer(); + DataBuffer destDB = dest.getDataBuffer(); + + ComponentSampleModel srcSM = (ComponentSampleModel) src.getSampleModel(); + ComponentSampleModel destSM = (ComponentSampleModel) dest.getSampleModel(); + + + // Calculate offset to data in the underlying arrays: + + int srcScanlineStride = srcSM.getScanlineStride(); + int destScanlineStride = destSM.getScanlineStride(); + int srcX = src.getMinX() - src.getSampleModelTranslateX(); + int srcY = src.getMinY() - src.getSampleModelTranslateY(); + int destX = dest.getMinX() - dest.getSampleModelTranslateX(); + int destY = dest.getMinY() - dest.getSampleModelTranslateY(); + + int numBands = srcSM.getNumBands(); + + /* We can't use getOffset(x, y) from the sample model since we + don't want the band offset added in. */ + + int srcOffset = + numBands*srcX + srcScanlineStride*srcY + // from sample model + srcDB.getOffset(); // from data buffer + + int destOffset = + numBands*destX + destScanlineStride*destY + // from sample model + destDB.getOffset(); // from data buffer + + // Determine how much, and how many times to blit. + + int rowSize = src.getWidth()*numBands; + int h = src.getHeight(); + + if ((rowSize == srcScanlineStride) && + (rowSize == destScanlineStride)) + { + // collapse scan line blits to one large blit. + rowSize *= h; + h = 1; + } + + + // Do blitting + + Object srcArray = Buffers.getData(srcDB); + Object destArray = Buffers.getData(destDB); + + for (int yd = 0; yd<h; yd++) + { + System.arraycopy(srcArray, srcOffset, + destArray, destOffset, + rowSize); + srcOffset += srcScanlineStride; + destOffset += destScanlineStride; + } + + + return dest; + } + + public Rectangle2D getBounds2D(Raster src) + { + return src.getBounds(); + } + + public WritableRaster createCompatibleDestRaster(Raster src) { + + /* FIXME: Maybe we should explicitly create a raster with a + tightly pixel packed sample model, rather than assuming + that the createCompatibleWritableRaster() method in Raster + will create one. */ + + return src.createCompatibleWritableRaster(); + } + + public Point2D getPoint2D(Point2D srcPoint, Point2D destPoint) + { + if (destPoint == null) + return (Point2D) srcPoint.clone(); + + destPoint.setLocation(srcPoint); + return destPoint; + } + + public RenderingHints getRenderingHints() + { + throw new UnsupportedOperationException("not implemented"); + } +} diff --git a/libjava/classpath/gnu/java/awt/EmbeddedWindow.java b/libjava/classpath/gnu/java/awt/EmbeddedWindow.java new file mode 100644 index 0000000..a85ce74 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/EmbeddedWindow.java @@ -0,0 +1,139 @@ +/* EmbeddedWindow.java -- + Copyright (C) 2003, 2004 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; + +import gnu.java.awt.peer.EmbeddedWindowPeer; +import gnu.java.security.action.SetAccessibleAction; + +import java.awt.Component; +import java.awt.Frame; +import java.awt.Toolkit; +import java.lang.reflect.Field; +import java.security.AccessController; + +/** + * Represents an AWT window that can be embedded into another + * application. + * + * @author Michael Koch (konqueror@gmx.de) + */ +public class EmbeddedWindow extends Frame +{ + private long handle; + + /** + * Creates a window to be embedded into another application. The + * window will only be embedded after its setHandle method has been + * called. + */ + public EmbeddedWindow () + { + super(); + this.handle = 0; + } + + /** + * Creates a window to be embedded into another application. + * + * @param handle the native handle to the screen area where the AWT + * window should be embedded + */ + public EmbeddedWindow (long handle) + { + super(); + this.handle = handle; + } + + /** + * Creates the native peer for this embedded window. + */ + public void addNotify() + { + // Assume we're using ClasspathToolkit + ClasspathToolkit tk = (ClasspathToolkit) getToolkit(); + + // Circumvent the package-privateness of the AWT internal + // java.awt.Component.peer member variable. + try + { + Field peerField = Component.class.getDeclaredField("peer"); + AccessController.doPrivileged(new SetAccessibleAction(peerField)); + peerField.set(this, tk.createEmbeddedWindow (this)); + } + catch (IllegalAccessException e) + { + // This should never happen. + } + catch (NoSuchFieldException e) + { + // This should never happen. + } + + super.addNotify(); + } + + /** + * If the native peer for this embedded window has been created, + * then setHandle will embed the window. If not, setHandle tells + * us where to embed ourselves when our peer is created. + * + * @param handle the native handle to the screen area where the AWT + * window should be embedded + */ + public void setHandle(long handle) + { + if (this.handle != 0) + throw new RuntimeException ("EmbeddedWindow is already embedded"); + + this.handle = handle; + if (getPeer() != null) + ((EmbeddedWindowPeer) getPeer()).embed (this.handle); + } + + /** + * Gets the native handle of the screen area where the window will + * be embedded. + * + * @return The native handle that was passed to the constructor. + */ + public long getHandle() + { + return handle; + } +} diff --git a/libjava/classpath/gnu/java/awt/EventModifier.java b/libjava/classpath/gnu/java/awt/EventModifier.java new file mode 100644 index 0000000..565fcbc --- /dev/null +++ b/libjava/classpath/gnu/java/awt/EventModifier.java @@ -0,0 +1,107 @@ +/* EventModifier.java -- tool for converting modifier bits to 1.4 syle + Copyright (C) 2002 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; + +import java.awt.event.InputEvent; + +public class EventModifier +{ + /** The mask for old events. */ + public static final int OLD_MASK = 0x3f; + + /** The mask for new events. */ + public static final int NEW_MASK = 0x3fc0; + + /** + * Non-instantiable. + */ + private EventModifier() + { + throw new InternalError(); + } + + /** + * Converts the old style modifiers (0x3f) to the new style (0xffffffc0). + * + * @param mod the modifiers to convert + * @return the adjusted modifiers + */ + public static int extend(int mod) + { + // Favor what we hope will be the common case. + if ((mod & OLD_MASK) == 0) + return mod; + if ((mod & InputEvent.SHIFT_MASK) != 0) + mod |= InputEvent.SHIFT_DOWN_MASK; + if ((mod & InputEvent.CTRL_MASK) != 0) + mod |= InputEvent.CTRL_DOWN_MASK; + if ((mod & InputEvent.META_MASK) != 0) + mod |= InputEvent.META_DOWN_MASK; + if ((mod & InputEvent.ALT_MASK) != 0) + mod |= InputEvent.ALT_DOWN_MASK; + if ((mod & InputEvent.BUTTON1_MASK) != 0) + mod |= InputEvent.BUTTON1_DOWN_MASK; + if ((mod & InputEvent.ALT_GRAPH_MASK) != 0) + mod |= InputEvent.ALT_GRAPH_DOWN_MASK; + return mod & ~OLD_MASK; + } + + /** + * Converts the new style modifiers (0xffffffc0) to the old style (0x3f). + * + * @param mod the modifiers to convert + * @return the adjusted modifiers + */ + public static int revert(int mod) + { + if ((mod & InputEvent.SHIFT_DOWN_MASK) != 0) + mod |= InputEvent.SHIFT_MASK; + if ((mod & InputEvent.CTRL_DOWN_MASK) != 0) + mod |= InputEvent.CTRL_MASK; + if ((mod & InputEvent.META_DOWN_MASK) != 0) + mod |= InputEvent.META_MASK; + if ((mod & InputEvent.ALT_DOWN_MASK) != 0) + mod |= InputEvent.ALT_MASK; + if ((mod & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) + mod |= InputEvent.ALT_GRAPH_MASK; + if ((mod & InputEvent.BUTTON1_DOWN_MASK) != 0) + mod |= InputEvent.BUTTON1_MASK; + return mod & OLD_MASK; + } +} // class EventModifier diff --git a/libjava/classpath/gnu/java/awt/FocusManager.java b/libjava/classpath/gnu/java/awt/FocusManager.java new file mode 100644 index 0000000..49b40bf --- /dev/null +++ b/libjava/classpath/gnu/java/awt/FocusManager.java @@ -0,0 +1,52 @@ +/* FocusManager.java -- Provide Swing FocusManager API compatibility + Copyright (C) 2005 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; + +/** + * This is a subclass of the otherwise abstract class + * {@link javax.swing.FocusManager}. Its sole purpose is to make the Swing + * FocusManager usable as a FocusManager in AWT, so that we can provide both + * the new (1.4) KeyboardFocusManager API and still support the older + * Swing FocusManager. + * + * @author Roman Kennke + */ +public class FocusManager + extends javax.swing.FocusManager +{ +} diff --git a/libjava/classpath/gnu/java/awt/GradientPaintContext.java b/libjava/classpath/gnu/java/awt/GradientPaintContext.java new file mode 100644 index 0000000..5e1d62d --- /dev/null +++ b/libjava/classpath/gnu/java/awt/GradientPaintContext.java @@ -0,0 +1,164 @@ +/* GradientPaintContext.java -- + Copyright (C) 2005, 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; + +import java.awt.geom.Point2D; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.PaintContext; +import java.awt.Color; + +/** + * A {@link PaintContext} used by the {@link GradientPaint} class. + */ +public class GradientPaintContext implements PaintContext +{ + + // This implementation follows the technique described in + // "Java(tm) 2D Graphics" by Jonathan Knudsen (O'Reilly 1999). + + /** The x-coordinate of the anchor point for color 1. */ + private final float x1; + + /** The y-coordinate of the anchor point for color 1. */ + private final float y1; + + /** Color 1. */ + private final Color c1; + + /** The x-coordinate of the anchor point for color 2. */ + private final float x2; + + /** The y-coordinate of the anchor point for color 2. */ + private final float y2; + + /** Color 2. */ + private final Color c2; + + /** A flag indicating whether the gradient is cyclic or acyclic. */ + private final boolean cyclic; + + /** The length of the gradient line - computed from the two anchor points. */ + private final double length; + + /** + * Creates a new instance. + * + * @param x1 the x-coordinate for the anchor point for color 1. + * @param y1 the y-coordinate for the anchor point for color 1. + * @param c1 color 1. + * @param x2 the x-coordinate for the anchor point for color 2. + * @param y2 the y-coordinate for the anchor point for color 2. + * @param c2 color 2. + * @param cyclic a flag that determines whether the gradient is cyclic + * or acyclic. + */ + public GradientPaintContext(float x1, float y1, Color c1, + float x2, float y2, Color c2, boolean cyclic) + { + this.x1 = x1; + this.y1 = y1; + this.c1 = c1; + this.x2 = x2; + this.y2 = y2; + this.c2 = c2; + this.cyclic = cyclic; + length = Point2D.distance(x1, y1, x2, y2); + } + + /** + * Return the color model of this context. It may be different from the + * hint specified during createContext, as not all contexts can generate + * color patterns in an arbitrary model. + * + * @return the context color model + */ + public ColorModel getColorModel() + { + return ColorModel.getRGBdefault(); + } + + /** + * Return a raster containing the colors for the graphics operation. + * + * @param x the x-coordinate, in device space + * @param y the y-coordinate, in device space + * @param w the width, in device space + * @param h the height, in device space + * @return a raster for the given area and color + */ + public Raster getRaster(int x, int y, int w, int h) { + ColorModel cm = getColorModel(); + WritableRaster raster = cm.createCompatibleWritableRaster(w, h); + int[] data = new int[w * h * 4]; + double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); + for (int r = 0; r < h; r++) { + for (int c = 0; c < w; c++) { + double u = 0.0; + if (pd2 != 0) + u = (((x + c) - x1) * (x2 - x1) + ((y + r) - y1) * (y2 - y1)) + / Math.sqrt(pd2); + double ratio = u / length; + if (cyclic) + ratio = Math.abs(ratio - Math.floor((ratio + 1.0) / 2.0) * 2.0); + else + ratio = Math.max(0.0, Math.min(1.0, ratio)); + int base = (r * w + c) * 4; + data[base] = (int) (c1.getRed() + ratio * (c2.getRed() - c1.getRed())); + data[base + 1] + = (int) (c1.getGreen() + ratio * (c2.getGreen() - c1.getGreen())); + data[base + 2] + = (int) (c1.getBlue() + ratio * (c2.getBlue() - c1.getBlue())); + data[base + 3] + = (int) (c1.getAlpha() + ratio * (c2.getAlpha() - c1.getAlpha())); + } + } + raster.setPixels(0, 0, w, h, data); + return raster; + } + + /** + * Release the resources allocated for the paint (none in this + * implementation). + */ + public void dispose() { + // nothing to do + } + +} diff --git a/libjava/classpath/gnu/java/awt/color/CieXyzConverter.java b/libjava/classpath/gnu/java/awt/color/CieXyzConverter.java new file mode 100644 index 0000000..1742805 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/CieXyzConverter.java @@ -0,0 +1,73 @@ +/* CieXyzConverter.java -- CieXyz conversion class + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * CieXyzConverter - converts to/from a D50-relative CIE XYZ color space. + * + * The sRGB<->CIE XYZ conversions in SrgbConverter are used. + * + * @author Sven de Marothy + */ +public class CieXyzConverter implements ColorSpaceConverter +{ + public float[] toCIEXYZ(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + public float[] fromCIEXYZ(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + public float[] toRGB(float[] in) + { + return SrgbConverter.XYZtoRGB(in); + } + + public float[] fromRGB(float[] in) + { + return SrgbConverter.RGBtoXYZ(in); + } +} diff --git a/libjava/classpath/gnu/java/awt/color/ClutProfileConverter.java b/libjava/classpath/gnu/java/awt/color/ClutProfileConverter.java new file mode 100644 index 0000000..bff97cc --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/ClutProfileConverter.java @@ -0,0 +1,152 @@ +/* ClutProfileConverter.java -- Conversion routines for CLUT-Based profiles + Copyright (C) 2004 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 gnu.java.awt.color; + +import java.awt.color.ICC_Profile; + + +/** + * ClutProfileConverter - conversions through a CLUT-based profile + * + * @author Sven de Marothy + */ +public class ClutProfileConverter implements ColorSpaceConverter +{ + private ColorLookUpTable toPCS; + private ColorLookUpTable fromPCS; + private int nChannels; + + public ClutProfileConverter(ICC_Profile profile) + { + nChannels = profile.getNumComponents(); + + // Sun does not specifiy which rendering intent should be used, + // neither does the ICC v2 spec really. + // Try intent 0 + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + if (toPCS != null || fromPCS != null) + return; + + // If no intent 0 clut is available, look for a intent 1 clut. + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB1Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA1Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + if (toPCS != null || fromPCS != null) + return; + + // Last shot.. intent 2 CLUT. + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB2Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA2Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + if (toPCS == null && fromPCS == null) + throw new IllegalArgumentException("No CLUTs in profile!"); + } + + public float[] toCIEXYZ(float[] in) + { + if (toPCS != null) + return toPCS.lookup(in); + else + return new float[3]; + } + + public float[] toRGB(float[] in) + { + return SrgbConverter.XYZtoRGB(toCIEXYZ(in)); + } + + public float[] fromCIEXYZ(float[] in) + { + if (fromPCS != null) + return fromPCS.lookup(in); + else + return new float[nChannels]; + } + + public float[] fromRGB(float[] in) + { + return fromCIEXYZ(SrgbConverter.RGBtoXYZ(in)); + } +} diff --git a/libjava/classpath/gnu/java/awt/color/ColorLookUpTable.java b/libjava/classpath/gnu/java/awt/color/ColorLookUpTable.java new file mode 100644 index 0000000..6b6418b --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/ColorLookUpTable.java @@ -0,0 +1,429 @@ +/* ColorLookUpTable.java -- ICC v2 CLUT + Copyright (C) 2004 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 gnu.java.awt.color; + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.nio.ByteBuffer; + + +/** + * ColorLookUpTable handles color lookups through a color lookup table, + * as defined in the ICC specification. + * Both 'mft2' and 'mft1' (8 and 16-bit) type CLUTs are handled. + * + * This will have to be updated later for ICC 4.0.0 + * + * @author Sven de Marothy + */ +public class ColorLookUpTable +{ + /** + * CIE 1931 D50 white point (in Lab coordinates) + */ + private static float[] D50 = { 0.96422f, 1.00f, 0.82521f }; + + /** + * Number of input/output channels + */ + int nIn; + + /** + * Number of input/output channels + */ + int nOut; + int nInTableEntries; // Number of input table entries + int nOutTableEntries; // Number of output table entries + int gridpoints; // Number of gridpoints + int nClut; // This is nOut*(gridpoints**nIn) + double[][] inTable; // 1D input table ([channel][table]) + short[][] outTable; // 1D input table ([channel][table]) + double[] clut; // The color lookup table + float[][] inMatrix; // input matrix (XYZ only) + boolean useMatrix; // Whether to use the matrix or not. + int[] multiplier; + int[] offsets; // Hypercube offsets + boolean inputLab; // Set if the CLUT input CS is Lab + boolean outputLab; // Set if the CLUT output CS is Lab + + /** + * Constructor + * Requires a profile file to get the CLUT from and the tag of the + * CLUT to create. (icSigXToYZTag where X,Y = [A | B], Z = [0,1,2]) + */ + public ColorLookUpTable(ICC_Profile profile, int tag) + { + useMatrix = false; + + switch (tag) + { + case ICC_Profile.icSigAToB0Tag: + case ICC_Profile.icSigAToB1Tag: + case ICC_Profile.icSigAToB2Tag: + if (profile.getColorSpaceType() == ColorSpace.TYPE_XYZ) + useMatrix = true; + inputLab = false; + outputLab = (profile.getPCSType() == ColorSpace.TYPE_Lab); + break; + case ICC_Profile.icSigBToA0Tag: + case ICC_Profile.icSigBToA1Tag: + case ICC_Profile.icSigBToA2Tag: + if (profile.getPCSType() == ColorSpace.TYPE_XYZ) + useMatrix = true; + inputLab = (profile.getPCSType() == ColorSpace.TYPE_Lab); + outputLab = false; + break; + default: + throw new IllegalArgumentException("Not a clut-type tag."); + } + + byte[] data = profile.getData(tag); + if (data == null) + throw new IllegalArgumentException("Unsuitable profile, does not contain a CLUT."); + + // check 'mft' + if (data[0] != 0x6d || data[1] != 0x66 || data[2] != 0x74) + throw new IllegalArgumentException("Unsuitable profile, invalid CLUT data."); + + if (data[3] == 0x32) + readClut16(data); + else if (data[3] == 0x31) + readClut8(data); + else + throw new IllegalArgumentException("Unknown/invalid CLUT type."); + } + + /** + * Loads a 16-bit CLUT into our data structures + */ + private void readClut16(byte[] data) + { + ByteBuffer buf = ByteBuffer.wrap(data); + + nIn = data[8] & (0xFF); + nOut = data[9] & (0xFF); + nInTableEntries = buf.getShort(48); + nOutTableEntries = buf.getShort(50); + gridpoints = data[10] & (0xFF); + + inMatrix = new float[3][3]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + inMatrix[i][j] = ((float) (buf.getInt(12 + (i * 3 + j) * 4))) / 65536.0f; + + inTable = new double[nIn][nInTableEntries]; + for (int channel = 0; channel < nIn; channel++) + for (int i = 0; i < nInTableEntries; i++) + inTable[channel][i] = (double) ((int) buf.getShort(52 + + (channel * nInTableEntries + + i) * 2) + & (0xFFFF)) / 65536.0; + + nClut = nOut; + multiplier = new int[nIn]; + multiplier[nIn - 1] = nOut; + for (int i = 0; i < nIn; i++) + { + nClut *= gridpoints; + if (i > 0) + multiplier[nIn - i - 1] = multiplier[nIn - i] * gridpoints; + } + + int clutOffset = 52 + nIn * nInTableEntries * 2; + clut = new double[nClut]; + for (int i = 0; i < nClut; i++) + clut[i] = (double) ((int) buf.getShort(clutOffset + i * 2) & (0xFFFF)) / 65536.0; + + outTable = new short[nOut][nOutTableEntries]; + for (int channel = 0; channel < nOut; channel++) + for (int i = 0; i < nOutTableEntries; i++) + outTable[channel][i] = buf.getShort(clutOffset + + (nClut + + channel * nOutTableEntries + i) * 2); + + // calculate the hypercube corner offsets + offsets = new int[(1 << nIn)]; + offsets[0] = 0; + for (int j = 0; j < nIn; j++) + { + int factor = 1 << j; + for (int i = 0; i < factor; i++) + offsets[factor + i] = offsets[i] + multiplier[j]; + } + } + + /** + * Loads a 8-bit CLUT into our data structures. + */ + private void readClut8(byte[] data) + { + ByteBuffer buf = ByteBuffer.wrap(data); + + nIn = (data[8] & (0xFF)); + nOut = (data[9] & (0xFF)); + nInTableEntries = 256; // always 256 + nOutTableEntries = 256; // always 256 + gridpoints = (data[10] & (0xFF)); + + inMatrix = new float[3][3]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + inMatrix[i][j] = ((float) (buf.getInt(12 + (i * 3 + j) * 4))) / 65536.0f; + + inTable = new double[nIn][nInTableEntries]; + for (int channel = 0; channel < nIn; channel++) + for (int i = 0; i < nInTableEntries; i++) + inTable[channel][i] = (double) ((int) buf.get(48 + + (channel * nInTableEntries + + i)) & (0xFF)) / 255.0; + + nClut = nOut; + multiplier = new int[nIn]; + multiplier[nIn - 1] = nOut; + for (int i = 0; i < nIn; i++) + { + nClut *= gridpoints; + if (i > 0) + multiplier[nIn - i - 1] = multiplier[nIn - i] * gridpoints; + } + + int clutOffset = 48 + nIn * nInTableEntries; + clut = new double[nClut]; + for (int i = 0; i < nClut; i++) + clut[i] = (double) ((int) buf.get(clutOffset + i) & (0xFF)) / 255.0; + + outTable = new short[nOut][nOutTableEntries]; + for (int channel = 0; channel < nOut; channel++) + for (int i = 0; i < nOutTableEntries; i++) + outTable[channel][i] = (short) (buf.get(clutOffset + nClut + + channel * nOutTableEntries + + i) * 257); + + // calculate the hypercube corner offsets + offsets = new int[(1 << nIn)]; + offsets[0] = 0; + for (int j = 0; j < nIn; j++) + { + int factor = 1 << j; + for (int i = 0; i < factor; i++) + offsets[factor + i] = offsets[i] + multiplier[j]; + } + } + + /** + * Performs a lookup through the Color LookUp Table. + * If the CLUT tag type is AtoB the conversion will be from the device + * color space to the PCS, BtoA type goes in the opposite direction. + * + * For convenience, the PCS values for input or output will always be + * CIE XYZ (D50), if the actual PCS is Lab, the values will be converted. + * + * N-dimensional linear interpolation is used. + */ + float[] lookup(float[] in) + { + float[] in2 = new float[in.length]; + if (useMatrix) + { + for (int i = 0; i < 3; i++) + in2[i] = in[0] * inMatrix[i][0] + in[1] * inMatrix[i][1] + + in[2] * inMatrix[i][2]; + } + else if (inputLab) + in2 = XYZtoLab(in); + else + System.arraycopy(in, 0, in2, 0, in.length); + + // input table + for (int i = 0; i < nIn; i++) + { + int index = (int) Math.floor(in2[i] * (double) (nInTableEntries - 1)); // floor in + + // clip values. + if (index >= nInTableEntries - 1) + in2[i] = (float) inTable[i][nInTableEntries - 1]; + else if (index < 0) + in2[i] = (float) inTable[i][0]; + else + { + // linear interpolation + double alpha = in2[i] * ((double) nInTableEntries - 1.0) - index; + in2[i] = (float) (inTable[i][index] * (1 - alpha) + + inTable[i][index + 1] * alpha); + } + } + + // CLUT lookup + double[] output2 = new double[nOut]; + double[] weights = new double[(1 << nIn)]; + double[] clutalpha = new double[nIn]; // interpolation values + int offset = 0; // = gp + for (int i = 0; i < nIn; i++) + { + int index = (int) Math.floor(in2[i] * ((double) gridpoints - 1.0)); + double alpha = in2[i] * ((double) gridpoints - 1.0) - (double) index; + + // clip values. + if (index >= gridpoints - 1) + { + index = gridpoints - 1; + alpha = 1.0; + } + else if (index < 0) + index = 0; + clutalpha[i] = alpha; + offset += index * multiplier[i]; + } + + // Calculate interpolation weights + weights[0] = 1.0; + for (int j = 0; j < nIn; j++) + { + int factor = 1 << j; + for (int i = 0; i < factor; i++) + { + weights[factor + i] = weights[i] * clutalpha[j]; + weights[i] *= (1.0 - clutalpha[j]); + } + } + + for (int i = 0; i < nOut; i++) + output2[i] = weights[0] * clut[offset + i]; + + for (int i = 1; i < (1 << nIn); i++) + { + int offset2 = offset + offsets[i]; + for (int f = 0; f < nOut; f++) + output2[f] += weights[i] * clut[offset2 + f]; + } + + // output table + float[] output = new float[nOut]; + for (int i = 0; i < nOut; i++) + { + int index = (int) Math.floor(output2[i] * ((double) nOutTableEntries + - 1.0)); + + // clip values. + if (index >= nOutTableEntries - 1) + output[i] = outTable[i][nOutTableEntries - 1]; + else if (index < 0) + output[i] = outTable[i][0]; + else + { + // linear interpolation + double a = output2[i] * ((double) nOutTableEntries - 1.0) + - (double) index; + output[i] = (float) ((double) ((int) outTable[i][index] & (0xFFFF)) * (1 + - a) + + (double) ((int) outTable[i][index + 1] & (0xFFFF)) * a) / 65536f; + } + } + + if (outputLab) + return LabtoXYZ(output); + return output; + } + + /** + * Converts CIE Lab coordinates to (D50) XYZ ones. + */ + private float[] LabtoXYZ(float[] in) + { + // Convert from byte-packed format to a + // more convenient one (actual Lab values) + // (See ICC spec for details) + // factor is 100 * 65536 / 65280 + in[0] = (float) (100.392156862745 * in[0]); + in[1] = (in[1] * 256.0f) - 128.0f; + in[2] = (in[2] * 256.0f) - 128.0f; + + float[] out = new float[3]; + + out[1] = (in[0] + 16.0f) / 116.0f; + out[0] = in[1] / 500.0f + out[1]; + out[2] = out[1] - in[2] / 200.0f; + + for (int i = 0; i < 3; i++) + { + double exp = out[i] * out[i] * out[i]; + if (exp <= 0.008856) + out[i] = (out[i] - 16.0f / 116.0f) / 7.787f; + else + out[i] = (float) exp; + out[i] = D50[i] * out[i]; + } + return out; + } + + /** + * Converts CIE XYZ coordinates to Lab ones. + */ + private float[] XYZtoLab(float[] in) + { + float[] temp = new float[3]; + + for (int i = 0; i < 3; i++) + { + temp[i] = in[i] / D50[i]; + + if (temp[i] <= 0.008856f) + temp[i] = (7.7870689f * temp[i]) + (16f / 116.0f); + else + temp[i] = (float) Math.exp((1.0 / 3.0) * Math.log(temp[i])); + } + + float[] out = new float[3]; + out[0] = (116.0f * temp[1]) - 16f; + out[1] = 500.0f * (temp[0] - temp[1]); + out[2] = 200.0f * (temp[1] - temp[2]); + + // Normalize to packed format + out[0] = (float) (out[0] / 100.392156862745); + out[1] = (out[1] + 128f) / 256f; + out[2] = (out[2] + 128f) / 256f; + for (int i = 0; i < 3; i++) + { + if (out[i] < 0f) + out[i] = 0f; + if (out[i] > 1f) + out[i] = 1f; + } + return out; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/ColorSpaceConverter.java b/libjava/classpath/gnu/java/awt/color/ColorSpaceConverter.java new file mode 100644 index 0000000..63ba08a --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/ColorSpaceConverter.java @@ -0,0 +1,69 @@ +/* ColorSpaceConverter.java -- an interface for colorspace conversion + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * ColorSpaceConverter - used by java.awt.color.ICC_ColorSpace + * + * Color space conversion can occur in several ways: + * + * -Directly (for the built in spaces sRGB, linear RGB, gray, CIE XYZ and PYCC + * -ICC_ProfileRGB works through TRC curves and a matrix + * -ICC_ProfileGray works through a single TRC + * -Everything else is done through Color lookup tables. + * + * The different conversion methods are implemented through + * an interface. The built-in colorspaces are implemented directly + * with the relevant conversion equations. + * + * In this way, we hopefully will always use the fastest and most + * accurate method available. + * + * @author Sven de Marothy + */ +public interface ColorSpaceConverter +{ + float[] toCIEXYZ(float[] in); + + float[] fromCIEXYZ(float[] in); + + float[] toRGB(float[] in); + + float[] fromRGB(float[] in); +} diff --git a/libjava/classpath/gnu/java/awt/color/GrayProfileConverter.java b/libjava/classpath/gnu/java/awt/color/GrayProfileConverter.java new file mode 100644 index 0000000..3c72513 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/GrayProfileConverter.java @@ -0,0 +1,137 @@ +/* GrayProfileConverter.java -- Gray profile conversion class + Copyright (C) 2004 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 gnu.java.awt.color; + +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileGray; +import java.awt.color.ProfileDataException; + +/** + * GrayProfileConverter - converts Grayscale profiles (ICC_ProfileGray) + * + * This type of profile contains a single tone reproduction curve (TRC). + * Conversion consists of simple TRC lookup. + * + * This implementation is very lazy and does everything applying the TRC and + * utilizing the built-in linear grayscale color space. + * + * @author Sven de Marothy + */ +public class GrayProfileConverter implements ColorSpaceConverter +{ + private GrayScaleConverter gc; + private ToneReproductionCurve trc; + private ColorLookUpTable toPCS; + private ColorLookUpTable fromPCS; + + /** + * Constructs the converter described by an ICC_ProfileGray object + */ + public GrayProfileConverter(ICC_ProfileGray profile) + { + try + { + trc = new ToneReproductionCurve(profile.getGamma()); + } + catch (ProfileDataException e) + { + trc = new ToneReproductionCurve(profile.getTRC()); + } + + // linear grayscale converter + gc = new GrayScaleConverter(); + + // If a CLUT is available, it should be used, and the TRCs ignored. + // Note: A valid profile may only have CLUTs in one direction, and + // TRC:s without useful info, making reverse-transforms impossible. + // In this case the TRC will be used for the reverse-transform with + // unpredictable results. This is in line with the Java specification, + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag); + } + catch (Exception e) + { + fromPCS = null; + } + } + + public float[] toCIEXYZ(float[] in) + { + if (toPCS != null) + return toPCS.lookup(in); + float[] gray = new float[1]; + gray[0] = trc.lookup(in[0]); + return gc.toCIEXYZ(gray); + } + + public float[] toRGB(float[] in) + { + float[] gray = new float[1]; + gray[0] = trc.lookup(in[0]); + return gc.toRGB(gray); + } + + public float[] fromRGB(float[] in) + { + // get linear grayscale value + float[] gray = gc.fromRGB(in); + gray[0] = trc.reverseLookup(gray[0]); + return gray; + } + + public float[] fromCIEXYZ(float[] in) + { + if (fromPCS != null) + return fromPCS.lookup(in); + + float[] gray = gc.fromCIEXYZ(in); + gray[0] = trc.reverseLookup(gray[0]); + return gray; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/GrayScaleConverter.java b/libjava/classpath/gnu/java/awt/color/GrayScaleConverter.java new file mode 100644 index 0000000..7a27ddb --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/GrayScaleConverter.java @@ -0,0 +1,110 @@ +/* GrayScaleConverter.java -- Linear grayscale conversion class + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * Linear Grayscale converter + * + * @author Sven de Marothy + */ +public class GrayScaleConverter implements ColorSpaceConverter +{ + // intensity factors (ITU Rec. BT.709) + double[] coeff = { 0.2125f, 0.7154f, 0.0721f }; + + /** + * CIE 1931 D50 white point (in Lab coordinates) + */ + private static float[] D50 = { 0.96422f, 1.00f, 0.82521f }; + + public float[] toCIEXYZ(float[] in) + { + float g = in[0]; + if (g < 0) + g = 1 + g; + float[] out = { g * D50[0], g * D50[1], g * D50[2] }; // White spot + return out; + } + + public float[] toRGB(float[] in) + { + float[] out = new float[3]; + if (in[0] <= 0.00304f) + out[0] = in[0] * 12.92f; + else + out[0] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(in[0]))) + - 0.055f; + out[1] = out[2] = out[0]; + return out; + } + + public float[] fromCIEXYZ(float[] in) + { + float[] temp = new float[3]; + temp[0] = 3.1338f * in[0] - 1.6171f * in[1] - 0.4907f * in[2]; + temp[1] = -0.9785f * in[0] + 1.9160f * in[1] + 0.0334f * in[2]; + temp[2] = 0.0720f * in[0] - 0.2290f * in[1] + 1.4056f * in[2]; + float[] out = new float[1]; + for (int i = 0; i < 3; i++) + out[0] = (float) (temp[i] * coeff[i]); + return out; + } + + public float[] fromRGB(float[] in) + { + float[] out = new float[1]; + + // Convert non-linear RGB coordinates to linear ones, + // numbers from the w3 spec. + out[0] = 0; + for (int i = 0; i < 3; i++) + { + float n = in[i]; + if (n < 0) + n = 0f; + if (n > 1) + n = 1f; + if (n <= 0.03928f) + out[0] += (float) (coeff[i] * n / 12.92); + else + out[0] += (float) (coeff[i] * Math.exp(2.4 * Math.log((n + 0.055) / 1.055))); + } + return out; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/LinearRGBConverter.java b/libjava/classpath/gnu/java/awt/color/LinearRGBConverter.java new file mode 100644 index 0000000..13a4e2c --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/LinearRGBConverter.java @@ -0,0 +1,152 @@ +/* LinearRGBConverter.java -- conversion to a linear RGB color space + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * LinearRGBConverter - conversion routines for a linear sRGB colorspace + * sRGB is a standard for RGB colorspaces, adopted by the w3c. + * + * The specification is available at: + * http://www.w3.org/Graphics/Color/sRGB.html + * + * @author Sven de Marothy + */ +public class LinearRGBConverter implements ColorSpaceConverter +{ + /** + * linear RGB --> sRGB + * Use the inverse gamma curve + */ + public float[] toRGB(float[] in) + { + float[] out = new float[3]; + for (int i = 0; i < 3; i++) + { + float n = in[i]; + if (n < 0) + n = 0f; + if (n > 1) + n = 1f; + if (n <= 0.00304f) + out[i] = in[0] * 12.92f; + else + out[i] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(n))) + - 0.055f; + } + return out; + } + + /** + * sRGB --> linear RGB + * Use the gamma curve (gamma=2.4 in sRGB) + */ + public float[] fromRGB(float[] in) + { + float[] out = new float[3]; + + // Convert non-linear RGB coordinates to linear ones, + // numbers from the w3 spec. + for (int i = 0; i < 3; i++) + { + float n = in[i]; + if (n < 0) + n = 0f; + if (n > 1) + n = 1f; + if (n <= 0.03928f) + out[i] = (float) (n / 12.92); + else + out[i] = (float) (Math.exp(2.4 * Math.log((n + 0.055) / 1.055))); + } + return out; + } + + /** + * Linear RGB --> CIE XYZ (D50 relative) + * This is a simple matrix transform, the matrix (relative D65) + * is given in the sRGB spec. This has been combined with a + * linear Bradford transform for the D65-->D50 mapping, resulting + * in a single matrix which does the whole thing. + * + */ + public float[] fromCIEXYZ(float[] in) + { + /* + * Note: The numbers which were used to calculate this only had four + * digits of accuracy. So don't be fooled by the number of digits here. + * If someone has more accurate source, feel free to update this. + */ + float[] out = new float[3]; + out[0] = (float) (3.13383065124221 * in[0] - 1.61711949411313 * in[1] + - 0.49071914111101 * in[2]); + out[1] = (float) (-0.97847026691142 * in[0] + 1.91597856031996 * in[1] + + 0.03340430640699 * in[2]); + out[2] = (float) (0.07203679486279 * in[0] - 0.22903073553113 * in[1] + + 1.40557835776234 * in[2]); + if (out[0] < 0) + out[0] = 0f; + if (out[1] < 0) + out[1] = 0f; + if (out[2] < 0) + out[2] = 0f; + if (out[0] > 1.0f) + out[0] = 1.0f; + if (out[1] > 1.0f) + out[1] = 1.0f; + if (out[2] > 1.0f) + out[2] = 1.0f; + return out; + } + + /** + * Linear RGB --> CIE XYZ (D50 relative) + * Uses the inverse of the above matrix. + */ + public float[] toCIEXYZ(float[] in) + { + float[] out = new float[3]; + out[0] = (float) (0.43606375022190 * in[0] + 0.38514960146481 * in[1] + + 0.14308641888799 * in[2]); + out[1] = (float) (0.22245089403542 * in[0] + 0.71692584775182 * in[1] + + 0.06062451125578 * in[2]); + out[2] = (float) (0.01389851860679 * in[0] + 0.09707969011198 * in[1] + + 0.71399604572506 * in[2]); + return out; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/ProfileHeader.java b/libjava/classpath/gnu/java/awt/color/ProfileHeader.java new file mode 100644 index 0000000..4fdef56 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/ProfileHeader.java @@ -0,0 +1,398 @@ +/* ProfileHeader.java -- Encapsules ICC Profile header data + Copyright (C) 2004 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 gnu.java.awt.color; + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.nio.ByteBuffer; + + +/** + * Header, abstracts and validates the header data. + * + * @author Sven de Marothy + */ +public class ProfileHeader +{ + /** + * Magic identifier (ASCII 'acsp') + */ + private static final int icMagicNumber = 0x61637370; + + /** + * Mapping from ICC Profile signatures to ColorSpace types + */ + private static final int[] csTypeMap = + { + ICC_Profile.icSigXYZData, + ColorSpace.TYPE_XYZ, + ICC_Profile.icSigLabData, + ColorSpace.TYPE_Lab, + ICC_Profile.icSigLuvData, + ColorSpace.TYPE_Luv, + ICC_Profile.icSigYCbCrData, + ColorSpace.TYPE_YCbCr, + ICC_Profile.icSigYxyData, + ColorSpace.TYPE_Yxy, + ICC_Profile.icSigRgbData, + ColorSpace.TYPE_RGB, + ICC_Profile.icSigGrayData, + ColorSpace.TYPE_GRAY, + ICC_Profile.icSigHsvData, + ColorSpace.TYPE_HSV, + ICC_Profile.icSigHlsData, + ColorSpace.TYPE_HLS, + ICC_Profile.icSigCmykData, + ColorSpace.TYPE_CMYK, + ICC_Profile.icSigCmyData, + ColorSpace.TYPE_CMY, + ICC_Profile.icSigSpace2CLR, + ColorSpace.TYPE_2CLR, + ICC_Profile.icSigSpace3CLR, + ColorSpace.TYPE_3CLR, + ICC_Profile.icSigSpace4CLR, + ColorSpace.TYPE_4CLR, + ICC_Profile.icSigSpace5CLR, + ColorSpace.TYPE_5CLR, + ICC_Profile.icSigSpace6CLR, + ColorSpace.TYPE_6CLR, + ICC_Profile.icSigSpace7CLR, + ColorSpace.TYPE_7CLR, + ICC_Profile.icSigSpace8CLR, + ColorSpace.TYPE_8CLR, + ICC_Profile.icSigSpace9CLR, + ColorSpace.TYPE_9CLR, + ICC_Profile.icSigSpaceACLR, + ColorSpace.TYPE_ACLR, + ICC_Profile.icSigSpaceBCLR, + ColorSpace.TYPE_BCLR, + ICC_Profile.icSigSpaceCCLR, + ColorSpace.TYPE_CCLR, + ICC_Profile.icSigSpaceDCLR, + ColorSpace.TYPE_DCLR, + ICC_Profile.icSigSpaceECLR, + ColorSpace.TYPE_ECLR, + ICC_Profile.icSigSpaceFCLR, + ColorSpace.TYPE_FCLR + }; + + /** + * Size of an ICC header (128 bytes) + */ + public static final int HEADERSIZE = 128; + + /** + * Mapping of ICC class signatures to profile class constants + */ + private static final int[] classMap = + { + ICC_Profile.icSigInputClass, + ICC_Profile.CLASS_INPUT, + ICC_Profile.icSigDisplayClass, + ICC_Profile.CLASS_DISPLAY, + ICC_Profile.icSigOutputClass, + ICC_Profile.CLASS_OUTPUT, + ICC_Profile.icSigLinkClass, + ICC_Profile.CLASS_DEVICELINK, + ICC_Profile.icSigColorSpaceClass, + ICC_Profile.CLASS_COLORSPACECONVERSION, + ICC_Profile.icSigAbstractClass, + ICC_Profile.CLASS_ABSTRACT, + ICC_Profile.icSigNamedColorClass, + ICC_Profile.CLASS_NAMEDCOLOR + }; + private int size; + private int cmmId; + + // Major/Minor version, The ICC-1998 spec is major v2 + private int majorVersion; + + // Major/Minor version, The ICC-1998 spec is major v2 + private int minorVersion; + private int profileClass; // profile device class + private int colorSpace; // data color space type + private int profileColorSpace; // profile connection space (PCS) type + private byte[] timestamp; // original creation timestamp + private int platform; // platform signature + private int flags; // flags + private int magic; // magic number. + private int manufacturerSig; // manufacturer sig + private int modelSig; // model sig + private byte[] attributes; // Attributes + private int intent; // rendering intent + private byte[] illuminant; // illuminant info (Coordinates of D50 in the PCS) + private int creatorSig; // Creator sig (same type as manufacturer) + + /** + * Creates a 'default' header for use with our predefined profiles. + * Note the device and profile color spaces are not set. + */ + public ProfileHeader() + { + creatorSig = 0; + intent = 0; + modelSig = manufacturerSig = (int) 0x6E6f6E65; // 'none' + magic = icMagicNumber; + cmmId = 0; + platform = 0; // no preferred platform + timestamp = new byte[8]; + majorVersion = 2; + minorVersion = 0x10; + flags = 0; + + // D50 in XYZ format (encoded) + illuminant = new byte[] + { + (byte) 0x00, (byte) 0x00, (byte) 0xf6, (byte) 0xd6, + (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0xd3, (byte) 0x2d + }; + attributes = new byte[8]; + profileClass = ICC_Profile.CLASS_DISPLAY; + } + + /** + * Creates a header from profile data. Only the header portion (128 bytes) + * is read, so the array passed need not be the full profile. + */ + public ProfileHeader(byte[] data) + { + ByteBuffer buf = ByteBuffer.wrap(data); + + // Get size (the sign bit shouldn't matter. + // A valid profile can never be +2Gb) + size = buf.getInt(ICC_Profile.icHdrSize); + + // CMM ID + cmmId = buf.getInt(ICC_Profile.icHdrCmmId); + + // Version number + majorVersion = (int) (data[ICC_Profile.icHdrVersion]); + minorVersion = (int) (data[ICC_Profile.icHdrVersion + 1]); + + // Profile/Device class + int classSig = buf.getInt(ICC_Profile.icHdrDeviceClass); + profileClass = -1; + for (int i = 0; i < classMap.length; i += 2) + if (classMap[i] == classSig) + { + profileClass = classMap[i + 1]; + break; + } + + // get the data color space + int csSig = buf.getInt(ICC_Profile.icHdrColorSpace); + colorSpace = -1; + for (int i = 0; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == csSig) + { + colorSpace = csTypeMap[i + 1]; + break; + } + + // get the profile color space (PCS), must be xyz or lab except + // for device-link-class profiles + int pcsSig = buf.getInt(ICC_Profile.icHdrPcs); + profileColorSpace = -1; + if (profileClass != ICC_Profile.CLASS_DEVICELINK) + { + if (pcsSig == ICC_Profile.icSigXYZData) + profileColorSpace = ColorSpace.TYPE_XYZ; + if (pcsSig == ICC_Profile.icSigLabData) + profileColorSpace = ColorSpace.TYPE_Lab; + } + else + { + for (int i = 0; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == pcsSig) + { + profileColorSpace = csTypeMap[i + 1]; + break; + } + } + + // creation timestamp + timestamp = new byte[8]; + System.arraycopy(data, ICC_Profile.icHdrDate, timestamp, 0, 8); + + // magic number + magic = buf.getInt(ICC_Profile.icHdrMagic); + + // platform info + platform = buf.getInt(ICC_Profile.icHdrPlatform); + // get flags + flags = buf.getInt(ICC_Profile.icHdrFlags); + // get manufacturer sign + manufacturerSig = buf.getInt(ICC_Profile.icHdrManufacturer); + // get header model + modelSig = buf.getInt(ICC_Profile.icHdrModel); + // attributes + attributes = new byte[8]; + System.arraycopy(data, ICC_Profile.icHdrAttributes, attributes, 0, 8); + // rendering intent + intent = buf.getInt(ICC_Profile.icHdrRenderingIntent); + // illuminant info + illuminant = new byte[12]; + System.arraycopy(data, ICC_Profile.icHdrIlluminant, illuminant, 0, 12); + // Creator signature + creatorSig = buf.getInt(ICC_Profile.icHdrCreator); + // The rest of the header (Total size: 128 bytes) is unused.. + } + + /** + * Verify that the header is valid + * @param size equals the file size if it is to be verified, -1 otherwise + * @throws IllegalArgumentException if the header is found to be invalid. + */ + public void verifyHeader(int size) throws IllegalArgumentException + { + // verify size + if (size != -1 && this.size != size) + throw new IllegalArgumentException("Invalid profile length:" + size); + + // Check version number + if (majorVersion != 2) + throw new IllegalArgumentException("Wrong major version number:" + + majorVersion); + + // Profile/Device class + if (profileClass == -1) + throw new IllegalArgumentException("Invalid profile/device class"); + + // get the data color space + if (colorSpace == -1) + throw new IllegalArgumentException("Invalid colorspace"); + + // profile color space + if (profileColorSpace == -1) + throw new IllegalArgumentException("Invalid PCS."); + + // check magic number + if (magic != icMagicNumber) + throw new IllegalArgumentException("Invalid magic number!"); + } + + /** + * Creates a header, setting the header file size at the same time. + * @param size the profile file size. + */ + public byte[] getData(int size) + { + byte[] data = new byte[HEADERSIZE]; + ByteBuffer buf = ByteBuffer.wrap(data); + buf.putInt(ICC_Profile.icHdrSize, size); + buf.putInt(ICC_Profile.icHdrCmmId, cmmId); + buf.putShort(ICC_Profile.icHdrVersion, + (short) (majorVersion << 8 | minorVersion)); + for (int i = 1; i < classMap.length; i += 2) + if (profileClass == classMap[i]) + buf.putInt(ICC_Profile.icHdrDeviceClass, classMap[i - 1]); + for (int i = 1; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == colorSpace) + buf.putInt(ICC_Profile.icHdrColorSpace, csTypeMap[i - 1]); + for (int i = 1; i < csTypeMap.length; i += 2) + if (csTypeMap[i] == profileColorSpace) + buf.putInt(ICC_Profile.icHdrPcs, csTypeMap[i - 1]); + + System.arraycopy(timestamp, 0, data, ICC_Profile.icHdrDate, + timestamp.length); + buf.putInt(ICC_Profile.icHdrMagic, icMagicNumber); + buf.putInt(ICC_Profile.icHdrPlatform, platform); + buf.putInt(ICC_Profile.icHdrFlags, flags); + buf.putInt(ICC_Profile.icHdrManufacturer, manufacturerSig); + buf.putInt(ICC_Profile.icHdrModel, modelSig); + System.arraycopy(attributes, 0, data, ICC_Profile.icHdrAttributes, + attributes.length); + buf.putInt(ICC_Profile.icHdrRenderingIntent, intent); + System.arraycopy(illuminant, 0, data, ICC_Profile.icHdrIlluminant, + illuminant.length); + buf.putInt(ICC_Profile.icHdrCreator, creatorSig); + return buf.array(); + } + + public int getSize() + { + return size; + } + + public void setSize(int s) + { + size = s; + } + + public int getMajorVersion() + { + return majorVersion; + } + + public int getMinorVersion() + { + return minorVersion; + } + + public int getProfileClass() + { + return profileClass; + } + + public void setProfileClass(int pc) + { + profileClass = pc; + } + + public int getColorSpace() + { + return colorSpace; + } + + public int getProfileColorSpace() + { + return profileColorSpace; + } + + public void setColorSpace(int cs) + { + colorSpace = cs; + } + + public void setProfileColorSpace(int pcs) + { + profileColorSpace = pcs; + } + +} diff --git a/libjava/classpath/gnu/java/awt/color/PyccConverter.java b/libjava/classpath/gnu/java/awt/color/PyccConverter.java new file mode 100644 index 0000000..cd50d87 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/PyccConverter.java @@ -0,0 +1,72 @@ +/* PyccConverter.java -- PhotoYCC conversion class + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * PyccConverter - conversion routines for the PhotoYCC colorspace + * + * Also known as PhotoCD YCC, it is an expansion of the conventional + * YCC color space to also include colors with over 100% white. + * + * XXX FIXME: Not yet implemented, implementation pending. + * + * @author Sven de Marothy + */ +public class PyccConverter implements ColorSpaceConverter +{ + public float[] toRGB(float[] in) + { + return null; + } + + public float[] fromRGB(float[] in) + { + return null; + } + + public float[] toCIEXYZ(float[] in) + { + return null; + } + + public float[] fromCIEXYZ(float[] in) + { + return null; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/RgbProfileConverter.java b/libjava/classpath/gnu/java/awt/color/RgbProfileConverter.java new file mode 100644 index 0000000..0cbd28f --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/RgbProfileConverter.java @@ -0,0 +1,244 @@ +/* RgbProfileConverter.java -- RGB Profile conversion class + Copyright (C) 2004 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 gnu.java.awt.color; + +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileRGB; +import java.awt.color.ProfileDataException; + +/** + * RgbProfileConverter - converts RGB profiles (ICC_ProfileRGB) + * + * This type of profile contains a matrix and three + * tone reproduction curves (TRCs). + * + * Device RGB --> CIE XYZ is done through first multiplying with + * a matrix, then each component is looked-up against it's TRC. + * + * The opposite transform is done using the inverse of the matrix, + * and TRC:s. + * + * @author Sven de Marothy + */ +public class RgbProfileConverter implements ColorSpaceConverter +{ + private float[][] matrix; + private float[][] inv_matrix; + private ToneReproductionCurve rTRC; + private ToneReproductionCurve gTRC; + private ToneReproductionCurve bTRC; + private ColorLookUpTable toPCS; + private ColorLookUpTable fromPCS; + + /** + * CIE 1931 D50 white point (in Lab coordinates) + */ + private static float[] D50 = { 0.96422f, 1.00f, 0.82521f }; + + /** + * Constructs an RgbProfileConverter from a given ICC_ProfileRGB + */ + public RgbProfileConverter(ICC_ProfileRGB profile) + { + toPCS = fromPCS = null; + matrix = profile.getMatrix(); + + // get TRCs + try + { + rTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.REDCOMPONENT)); + } + catch (ProfileDataException e) + { + rTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.REDCOMPONENT)); + } + try + { + gTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.GREENCOMPONENT)); + } + catch (ProfileDataException e) + { + gTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.GREENCOMPONENT)); + } + try + { + bTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.BLUECOMPONENT)); + } + catch (ProfileDataException e) + { + bTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.BLUECOMPONENT)); + } + + // If a CLUT is available, it should be used, and the TRCs ignored. + // Note: A valid profile may only have CLUTs in one direction, and + // TRC:s without useful info, making reverse-transforms impossible. + // In this case the TRC will be used for the reverse-transform with + // unpredictable results. This is in line with the Java specification, + try + { + toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag); + } + catch (Exception e) + { + toPCS = null; + } + + try + { + fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag); + } + catch (Exception e) + { + fromPCS = null; + } + + // Calculate the inverse matrix if no reverse CLUT is available + if(fromPCS == null) + inv_matrix = invertMatrix(matrix); + else + { + // otherwise just set it to an identity matrix + inv_matrix = new float[3][3]; + inv_matrix[0][0] = inv_matrix[1][1] = inv_matrix[2][2] = 1.0f; + } + } + + public float[] toCIEXYZ(float[] in) + { + // CLUT takes precedence + if (toPCS != null) + return toPCS.lookup(in); + + float[] temp = new float[3]; + float[] out = new float[3]; + + // device space --> linear gamma + temp[0] = rTRC.lookup(in[0]); + temp[1] = gTRC.lookup(in[1]); + temp[2] = bTRC.lookup(in[2]); + + // matrix multiplication + out[0] = matrix[0][0] * temp[0] + matrix[0][1] * temp[1] + + matrix[0][2] * temp[2]; + out[1] = matrix[1][0] * temp[0] + matrix[1][1] * temp[1] + + matrix[1][2] * temp[2]; + out[2] = matrix[2][0] * temp[0] + matrix[2][1] * temp[1] + + matrix[2][2] * temp[2]; + + return out; + } + + public float[] toRGB(float[] in) + { + return SrgbConverter.XYZtoRGB(toCIEXYZ(in)); + } + + public float[] fromCIEXYZ(float[] in) + { + if (fromPCS != null) + return fromPCS.lookup(in); + + float[] temp = new float[3]; + float[] out = new float[3]; + + // matrix multiplication + temp[0] = inv_matrix[0][0] * in[0] + inv_matrix[0][1] * in[1] + + inv_matrix[0][2] * in[2]; + temp[1] = inv_matrix[1][0] * in[0] + inv_matrix[1][1] * in[1] + + inv_matrix[1][2] * in[2]; + temp[2] = inv_matrix[2][0] * in[0] + inv_matrix[2][1] * in[1] + + inv_matrix[2][2] * in[2]; + + // device space --> linear gamma + out[0] = rTRC.reverseLookup(temp[0]); + out[1] = gTRC.reverseLookup(temp[1]); + out[2] = bTRC.reverseLookup(temp[2]); + + // FIXME: Sun appears to clip the return values to [0,1] + // I don't believe that is a Good Thing, + // (some colorspaces may allow values outside that range.) + // So we return the actual values here. + return out; + } + + public float[] fromRGB(float[] in) + { + return fromCIEXYZ(SrgbConverter.RGBtoXYZ(in)); + } + + /** + * Inverts a 3x3 matrix, returns the inverse, + * throws an IllegalArgumentException if the matrix is not + * invertible (this shouldn't happen for a valid profile) + */ + private float[][] invertMatrix(float[][] matrix) + { + float[][] out = new float[3][3]; + double determinant = matrix[0][0] * (matrix[1][1] * matrix[2][2] + - matrix[2][1] * matrix[1][2]) + - matrix[0][1] * (matrix[1][0] * matrix[2][2] + - matrix[2][0] * matrix[1][2]) + + matrix[0][2] * (matrix[1][0] * matrix[2][1] + - matrix[2][0] * matrix[1][1]); + + if (determinant == 0.0) + throw new IllegalArgumentException("Can't invert conversion matrix."); + float invdet = (float) (1.0 / determinant); + + out[0][0] = invdet * (matrix[1][1] * matrix[2][2] + - matrix[1][2] * matrix[2][1]); + out[0][1] = invdet * (matrix[0][2] * matrix[2][1] + - matrix[0][1] * matrix[2][2]); + out[0][2] = invdet * (matrix[0][1] * matrix[1][2] + - matrix[0][2] * matrix[1][1]); + out[1][0] = invdet * (matrix[1][2] * matrix[2][0] + - matrix[1][0] * matrix[2][2]); + out[1][1] = invdet * (matrix[0][0] * matrix[2][2] + - matrix[0][2] * matrix[2][0]); + out[1][2] = invdet * (matrix[0][2] * matrix[1][0] + - matrix[0][0] * matrix[1][2]); + out[2][0] = invdet * (matrix[1][0] * matrix[2][1] + - matrix[1][1] * matrix[2][0]); + out[2][1] = invdet * (matrix[0][1] * matrix[2][0] + - matrix[0][0] * matrix[2][1]); + out[2][2] = invdet * (matrix[0][0] * matrix[1][1] + - matrix[0][1] * matrix[1][0]); + return out; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/SrgbConverter.java b/libjava/classpath/gnu/java/awt/color/SrgbConverter.java new file mode 100644 index 0000000..a30a0db --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/SrgbConverter.java @@ -0,0 +1,152 @@ +/* SrgbConverter.java -- sRGB conversion class + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * SrgbConverter - conversion routines for the sRGB colorspace + * sRGB is a standard for RGB colorspaces, adopted by the w3c. + * + * The specification is available at: + * http://www.w3.org/Graphics/Color/sRGB.html + * + * @author Sven de Marothy + */ +/** + * + * Note the matrix numbers used here are NOT identical to those in the + * w3 spec, as those numbers are CIE XYZ relative a D65 white point. + * The CIE XYZ we use is relative a D50 white point, so therefore a + * linear Bradford transform matrix for D65->D50 mapping has been applied. + * (The ICC documents describe this transform) + * + * Linearized Bradford transform: + * 0.8951 0.2664 -0.1614 + * -0.7502 1.7135 0.0367 + * 0.0389 -0.0685 1.0296 + * + * Inverse: + * 0.9870 -0.1471 0.1600 + * 0.4323 0.5184 0.0493 + * -0.00853 0.0400 0.9685 + */ +public class SrgbConverter implements ColorSpaceConverter +{ + public float[] fromCIEXYZ(float[] in) + { + return XYZtoRGB(in); + } + + public float[] toCIEXYZ(float[] in) + { + return RGBtoXYZ(in); + } + + public float[] toRGB(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + public float[] fromRGB(float[] in) + { + float[] out = new float[3]; + System.arraycopy(in, 0, out, 0, 3); + return out; + } + + /** + * CIE XYZ (D50 relative) --> sRGB + * + * Static as it's used by other ColorSpaceConverters to + * convert to sRGB if the color space is defined in XYZ. + */ + public static float[] XYZtoRGB(float[] in) + { + float[] temp = new float[3]; + temp[0] = 3.1338f * in[0] - 1.6171f * in[1] - 0.4907f * in[2]; + temp[1] = -0.9785f * in[0] + 1.9160f * in[1] + 0.0334f * in[2]; + temp[2] = 0.0720f * in[0] - 0.2290f * in[1] + 1.4056f * in[2]; + + float[] out = new float[3]; + for (int i = 0; i < 3; i++) + { + if (temp[i] < 0) + temp[i] = 0.0f; + if (temp[i] > 1) + temp[i] = 1.0f; + if (temp[i] <= 0.00304f) + out[i] = temp[i] * 12.92f; + else + out[i] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(temp[i]))) + - 0.055f; + } + return out; + } + + /** + * sRGB --> CIE XYZ (D50 relative) + * + * Static as it's used by other ColorSpaceConverters to + * convert to XYZ if the color space is defined in RGB. + */ + public static float[] RGBtoXYZ(float[] in) + { + float[] temp = new float[3]; + float[] out = new float[3]; + for (int i = 0; i < 3; i++) + if (in[i] <= 0.03928f) + temp[i] = in[i] / 12.92f; + else + temp[i] = (float) Math.exp(2.4 * Math.log((in[i] + 0.055) / 1.055)); + + /* + * Note: The numbers which were used to calculate this only had four + * digits of accuracy. So don't be fooled by the number of digits here. + * If someone has more accurate source, feel free to update this. + */ + out[0] = (float) (0.436063750222 * temp[0] + 0.385149601465 * temp[1] + + 0.143086418888 * temp[2]); + out[1] = (float) (0.222450894035 * temp[0] + 0.71692584775 * temp[1] + + 0.060624511256 * temp[2]); + out[2] = (float) (0.0138985186 * temp[0] + 0.097079690112 * temp[1] + + 0.713996045725 * temp[2]); + return out; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/TagEntry.java b/libjava/classpath/gnu/java/awt/color/TagEntry.java new file mode 100644 index 0000000..a978646 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/TagEntry.java @@ -0,0 +1,121 @@ +/* TagEntry.java -- A utility class used for storing the tags in ICC_Profile + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * TagEntry - stores a profile tag. + * These are conveniently stored in a hashtable with the tag signature + * as a key. A legal profile can only have one tag with a given sig, + * so we can conveniently ignore collisions. + * + * @author Sven de Marothy + */ +public class TagEntry +{ + // tag table entry size + public static final int entrySize = 12; + private int signature; + private int size; + private int offset; + private byte[] data; + + public TagEntry(int sig, int offset, int size, byte[] data) + { + this.signature = sig; + this.offset = offset; + this.size = size; + this.data = new byte[size]; + System.arraycopy(data, offset, this.data, 0, size); + } + + public TagEntry(int sig, byte[] data) + { + this.signature = sig; + this.size = data.length; + this.data = new byte[size]; + System.arraycopy(data, offset, this.data, 0, size); + } + + public byte[] getData() + { + byte[] d = new byte[size]; + System.arraycopy(this.data, 0, d, 0, size); + return d; + } + + public String hashKey() + { + return tagHashKey(signature); + } + + public String toString() + { + String s = ""; + s = s + (char) ((byte) ((signature >> 24) & 0xFF)); + s = s + (char) ((byte) ((signature >> 16) & 0xFF)); + s = s + (char) ((byte) ((signature >> 8) & 0xFF)); + s = s + (char) ((byte) (signature & 0xFF)); + return s; + } + + public int getSignature() + { + return signature; + } + + public int getSize() + { + return size; + } + + public int getOffset() + { + return offset; + } + + public void setOffset(int offset) + { + this.offset = offset; + } + + public static String tagHashKey(int sig) + { + return "" + sig; + } +} diff --git a/libjava/classpath/gnu/java/awt/color/ToneReproductionCurve.java b/libjava/classpath/gnu/java/awt/color/ToneReproductionCurve.java new file mode 100644 index 0000000..a1bccbd --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/ToneReproductionCurve.java @@ -0,0 +1,177 @@ +/* ToneReproductionCurve.java -- Representation of an ICC 'curv' type TRC + Copyright (C) 2004 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 gnu.java.awt.color; + + +/** + * ToneReproductionCurve - TRCs are used to describe RGB + * and Grayscale profiles. The TRC is essentially the gamma + * function of the color space. + * + * For example, Apple RGB has a gamma of 1.8, most monitors are ~2.2, + * sRGB is 2.4 with a small linear part near 0. + * Linear spaces are of course 1.0. + * (The exact function is implemented in SrgbConverter) + * + * The ICC specification allows the TRC to be described as a single + * Gamma value, where the function is thus out = in**gamma. + * Alternatively, the gamma function may be represented by a lookup table + * of values, in which case linear interpolation is used. + * + * @author Sven de Marothy + */ +public class ToneReproductionCurve +{ + private float[] trc; + private float gamma; + private float[] reverseTrc; + + /** + * Constructs a TRC from a gamma values + */ + public ToneReproductionCurve(float gamma) + { + trc = null; + reverseTrc = null; + this.gamma = gamma; + } + + /** + * Constructs a TRC from a set of float values + */ + public ToneReproductionCurve(float[] trcValues) + { + trc = new float[trcValues.length]; + System.arraycopy(trcValues, 0, trc, 0, trcValues.length); + setupReverseTrc(); + } + + /** + * Constructs a TRC from a set of short values normalized to + * the 0-65535 range (as in the ICC profile file). + * (Note the values are treated as unsigned) + */ + public ToneReproductionCurve(short[] trcValues) + { + trc = new float[trcValues.length]; + for (int i = 0; i < trcValues.length; i++) + trc[i] = (float) ((int) trcValues[i] & (0xFFFF)) / 65535.0f; + setupReverseTrc(); + } + + /** + * Performs a TRC lookup + */ + public float lookup(float in) + { + float out; + + if (trc == null) + { + if (in == 0f) + return 0.0f; + return (float) Math.exp(gamma * Math.log(in)); + } + else + { + double alpha = in * (trc.length - 1); + int index = (int) Math.floor(alpha); + alpha = alpha - (double) index; + if (index >= trc.length - 1) + return trc[trc.length - 1]; + if (index <= 0) + return trc[0]; + out = (float) (trc[index] * (1.0 - alpha) + trc[index + 1] * alpha); + } + return out; + } + + /** + * Performs an reverse lookup + */ + public float reverseLookup(float in) + { + float out; + + if (trc == null) + { + if (in == 0f) + return 0.0f; + return (float) Math.exp((1.0 / gamma) * Math.log(in)); + } + else + { + double alpha = in * (reverseTrc.length - 1); + int index = (int) Math.floor(alpha); + alpha = alpha - (double) index; + if (index >= reverseTrc.length - 1) + return reverseTrc[reverseTrc.length - 1]; + if (index <= 0) + return reverseTrc[0]; + out = (float) (reverseTrc[index] * (1.0 - alpha) + + reverseTrc[index + 1] * alpha); + } + return out; + } + + /** + * Calculates a reverse-lookup table. + * We use a whopping 10,000 entries.. This is should be more than any + * real-life TRC table (typically around 256-1024) so we won't be losing + * any precision. + * + * This will of course generate completely invalid results if the curve + * is not monotonic and invertable. But what's the alternative? + */ + public void setupReverseTrc() + { + reverseTrc = new float[10000]; + int j = 0; + for (int i = 0; i < 10000; i++) + { + float n = ((float) i) / 10000f; + while (trc[j + 1] < n && j < trc.length - 2) + j++; + + if (j == trc.length - 2) + reverseTrc[i] = trc[trc.length - 1]; + else + reverseTrc[i] = (j + (n - trc[j]) / (trc[j + 1] - trc[j])) / ((float) trc.length); + } + } +} diff --git a/libjava/classpath/gnu/java/awt/color/package.html b/libjava/classpath/gnu/java/awt/color/package.html new file mode 100644 index 0000000..c4705cc --- /dev/null +++ b/libjava/classpath/gnu/java/awt/color/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in gnu.java.awt.color package. + Copyright (C) 2005 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. --> + +<html> +<head><title>GNU Classpath - gnu.java.awt.color</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/gnu/java/awt/doc-files/BitwiseXORComposite-1.png b/libjava/classpath/gnu/java/awt/doc-files/BitwiseXORComposite-1.png Binary files differnew file mode 100644 index 0000000..588c910 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/doc-files/BitwiseXORComposite-1.png diff --git a/libjava/classpath/gnu/java/awt/image/ImageDecoder.java b/libjava/classpath/gnu/java/awt/image/ImageDecoder.java new file mode 100644 index 0000000..141c854 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/image/ImageDecoder.java @@ -0,0 +1,156 @@ +/* ImageDecoder.java -- + Copyright (C) 1999, 2000, 2004 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.image; + +import java.awt.image.ImageConsumer; +import java.awt.image.ImageProducer; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Vector; + +public abstract class ImageDecoder implements ImageProducer +{ + Vector consumers = new Vector (); + String filename; + URL url; + byte[] data; + int offset; + int length; + InputStream input; + + static + { + // FIXME: there was some broken code here that looked like + // it wanted to rely on this property. I don't have any idea + // what it was intended to do. + // String endian = System.getProperties ().getProperty ("gnu.cpu.endian"); + } + + public ImageDecoder (String filename) + { + this.filename = filename; + } + + public ImageDecoder (URL url) + { + this.url = url; + } + + public ImageDecoder (InputStream is) + { + this.input = is; + } + + public ImageDecoder (byte[] imagedata, int imageoffset, int imagelength) + { + data = imagedata; + offset = imageoffset; + length = imagelength; + } + + public void addConsumer (ImageConsumer ic) + { + consumers.addElement (ic); + } + + public boolean isConsumer (ImageConsumer ic) + { + return consumers.contains (ic); + } + + public void removeConsumer (ImageConsumer ic) + { + consumers.removeElement (ic); + } + + public void startProduction (ImageConsumer ic) + { + if (!isConsumer(ic)) + addConsumer(ic); + + Vector list = (Vector) consumers.clone (); + try + { + // Create the input stream here rather than in the + // ImageDecoder constructors so that exceptions cause + // imageComplete to be called with an appropriate error + // status. + if (input == null) + { + try + { + if (url != null) + input = url.openStream(); + else + { + if (filename != null) + input = new FileInputStream (filename); + else + input = new ByteArrayInputStream (data, offset, length); + } + produce (list, input); + } + finally + { + input = null; + } + } + else + { + produce (list, input); + } + } + catch (Exception e) + { + for (int i = 0; i < list.size (); i++) + { + ImageConsumer ic2 = (ImageConsumer) list.elementAt (i); + ic2.imageComplete (ImageConsumer.IMAGEERROR); + } + } + } + + public void requestTopDownLeftRightResend (ImageConsumer ic) + { + } + + public abstract void produce (Vector v, InputStream is) throws IOException; +} diff --git a/libjava/classpath/gnu/java/awt/image/XBMDecoder.java b/libjava/classpath/gnu/java/awt/image/XBMDecoder.java new file mode 100644 index 0000000..0793d8e --- /dev/null +++ b/libjava/classpath/gnu/java/awt/image/XBMDecoder.java @@ -0,0 +1,155 @@ +/* XBMDecoder.java -- Decodes X-bitmaps + Copyright (C) 1999, 2004 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.image; + +import java.awt.image.ColorModel; +import java.awt.image.ImageConsumer; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.StringTokenizer; +import java.util.Vector; + +public class XBMDecoder extends ImageDecoder +{ + BufferedReader reader; + static final ColorModel cm = ColorModel.getRGBdefault (); + static final int black = 0xff000000; + static final int transparent = 0x00000000; + static final int masktable[] = { 0x01, 0x02, 0x04, 0x08, + 0x10, 0x20, 0x40, 0x80 }; + + public XBMDecoder (String filename) + { + super (filename); + } + + public XBMDecoder (URL url) + { + super (url); + } + + public void produce (Vector v, InputStream is) throws IOException + { + reader = new BufferedReader (new InputStreamReader (is)); + int width = -1, height = -1; + + for (int i = 0; i < 2; i++) + { + String line = reader.readLine (); + StringTokenizer st = new StringTokenizer (line); + + st.nextToken (); // #define + st.nextToken (); // name_[width|height] + if (i == 0) + width = Integer.parseInt (st.nextToken (), 10); + else + height = Integer.parseInt (st.nextToken (), 10); + } + + for (int i = 0; i < v.size (); i++) + { + ImageConsumer ic = (ImageConsumer) v.elementAt (i); + + ic.setDimensions (width, height); + ic.setColorModel (cm); + ic.setHints (ImageConsumer.COMPLETESCANLINES + | ImageConsumer.SINGLEFRAME + | ImageConsumer.SINGLEPASS + | ImageConsumer.TOPDOWNLEFTRIGHT); + } + + /* skip to the byte array */ + while (reader.read () != '{') { } + + /* loop through each scanline */ + for (int line = 0; line < height; line++) + { + int scanline[] = getScanline (reader, width); + + for (int i = 0; i < v.size (); i++) + { + ImageConsumer ic = (ImageConsumer) v.elementAt (i); + ic.setPixels (0, 0 + line, width, 1, cm, scanline, 0, width); + } + } + + /* tell each ImageConsumer that we're finished */ + for (int i = 0; i < v.size (); i++) + { + ImageConsumer ic = (ImageConsumer) v.elementAt (i); + ic.imageComplete (ImageConsumer.STATICIMAGEDONE); + } + } + + public static int[] getScanline (Reader in, int len) throws IOException + { + char byteStr[] = new char[2]; + int scanline[] = new int[len]; + int x = 0; + + while (x < len) + { + int ch = in.read (); + if (ch == '0') + { + in.read (); // 'x' + + byteStr[0] = (char) in.read (); + byteStr[1] = (char) in.read (); + + int byteVal = Integer.parseInt (new String (byteStr), 16); + + for (int i = 0; i < 8; i++, x++) + { + if (x == len) // condition occurs if bitmap is padded + return scanline; + + scanline[x] = ((byteVal & masktable[i]) != 0) ? + black : transparent; + } + } + } + + return scanline; + } +} diff --git a/libjava/classpath/gnu/java/awt/image/package.html b/libjava/classpath/gnu/java/awt/image/package.html new file mode 100644 index 0000000..8823367 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/image/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in gnu.java.awt.image package. + Copyright (C) 2005 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. --> + +<html> +<head><title>GNU Classpath - gnu.java.awt.image</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/gnu/java/awt/package.html b/libjava/classpath/gnu/java/awt/package.html new file mode 100644 index 0000000..1661685 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in gnu.java.awt package. + Copyright (C) 2005 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. --> + +<html> +<head><title>GNU Classpath - gnu.java.awt</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java new file mode 100644 index 0000000..78ab3a9 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java @@ -0,0 +1,846 @@ +/* ClasspathFontPeer.java -- Font peer used by GNU Classpath. + Copyright (C) 2003, 2004 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; + +import gnu.java.awt.ClasspathToolkit; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Toolkit; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.font.TextAttribute; +import java.awt.font.TransformAttribute; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.peer.FontPeer; +import java.text.AttributedCharacterIterator; +import java.text.CharacterIterator; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * A peer for fonts that are used inside Classpath. The purpose of + * this interface is to abstract from platform-specific font handling + * in the Classpath implementation of java.awt.Font and related + * classes. + * + * <p><b>State kept by the peer:</b> a peer is generated for each Font + * object in the default implementation. If you wish to share peers between + * fonts, you will need to subclass both ClasspathFontPeer and + * {@link ClasspathToolKit}.</p> + * + * <p><b>Thread Safety:</b> Methods of this interface may be called + * from arbitrary threads at any time. Implementations of the + * <code>ClasspathFontPeer</code> interface are required to perform + * the necessary synchronization.</p> + * + * @see java.awt.Font#getPeer + * @see java.awt.Toolkit#getFontPeer + * + * @author Sascha Brawer (brawer@dandelis.ch) + * @author Graydon Hoare (graydon@redhat.com) + */ +public abstract class ClasspathFontPeer + implements FontPeer +{ + + /*************************************************************************/ + + /* + * Instance Variables + */ + + /** + * The 3 names of this font. all fonts have 3 names, some of which + * may be equal: + * + * logical -- name the font was constructed from + * family -- a designer or brand name (Helvetica) + * face -- specific instance of a design (Helvetica Regular) + * + * @see isLogicalFontName + */ + + protected String logicalName; + protected String familyName; + protected String faceName; + + /** + * The font style, which is a combination (by OR-ing) of the font style + * constants PLAIN, BOLD and ITALIC, in this class. + */ + protected int style; + + /** + * The font point size. A point is 1/72 of an inch. + */ + protected float size; + + /** + * The affine transformation the font is currently subject to. + */ + protected AffineTransform transform; + + protected static ClasspathToolkit tk() + { + return (ClasspathToolkit)(Toolkit.getDefaultToolkit ()); + } + + /* + * Confusingly, a Logical Font is a concept unrelated to + * a Font's Logical Name. + * + * A Logical Font is one of 6 built-in, abstract font types + * which must be supported by any java environment: SansSerif, + * Serif, Monospaced, Dialog, and DialogInput. + * + * A Font's Logical Name is the name the font was constructed + * from. This might be the name of a Logical Font, or it might + * be the name of a Font Face. + */ + + protected static boolean isLogicalFontName(String name) + { + String uname = name.toUpperCase (); + return (uname.equals ("SANSSERIF") || + uname.equals ("SERIF") || + uname.equals ("MONOSPACED") || + uname.equals ("DIALOG") || + uname.equals ("DIALOGINPUT")); + } + + protected static String logicalFontNameToFaceName (String name) + { + String uname = name.toUpperCase (); + if (uname.equals("SANSSERIF")) + return "Helvetica"; + else if (uname.equals ("SERIF")) + return "Times"; + else if (uname.equals ("MONOSPACED")) + return "Courier"; + else if (uname.equals ("DIALOG")) + return "Helvetica"; + else if (uname.equals ("DIALOGINPUT")) + return "Helvetica"; + else + return "Helvetica"; + } + + protected static String faceNameToFamilyName (String name) + { + return name; + } + + public static void copyStyleToAttrs (int style, Map attrs) + { + if ((style & Font.BOLD) == Font.BOLD) + attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); + else + attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR); + + if ((style & Font.ITALIC) == Font.ITALIC) + attrs.put (TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE); + else + attrs.put (TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR); + } + + protected static void copyFamilyToAttrs (String fam, Map attrs) + { + if (fam != null) + attrs.put (TextAttribute.FAMILY, fam); + } + + public static void copySizeToAttrs (float size, Map attrs) + { + attrs.put (TextAttribute.SIZE, new Float (size)); + } + + protected static void copyTransformToAttrs (AffineTransform trans, Map attrs) + { + if (trans != null) + attrs.put(TextAttribute.TRANSFORM, new TransformAttribute (trans)); + } + + + protected void setStandardAttributes (String name, String family, int style, + float size, AffineTransform trans) + { + this.logicalName = name; + + if (isLogicalFontName (name)) + this.faceName = logicalFontNameToFaceName (name); + else + this.faceName = name; + + if (family != null) + this.familyName = family; + else + this.familyName = faceNameToFamilyName (faceName); + + this.style = style; + this.size = size; + this.transform = trans; + } + + + protected void setStandardAttributes (String name, Map attribs) + { + String family = this.familyName; + AffineTransform trans = this.transform; + float size = this.size; + int style = this.style; + + if (attribs.containsKey (TextAttribute.FAMILY)) + family = (String) attribs.get (TextAttribute.FAMILY); + + if (name == null) + name = "SansSerif"; + + if (attribs.containsKey (TextAttribute.WEIGHT)) + { + Float weight = (Float) attribs.get (TextAttribute.WEIGHT); + if (weight.floatValue () >= TextAttribute.WEIGHT_BOLD.floatValue ()) + style += Font.BOLD; + } + + if (attribs.containsKey (TextAttribute.POSTURE)) + { + Float posture = (Float) attribs.get (TextAttribute.POSTURE); + if (posture.floatValue () >= TextAttribute.POSTURE_OBLIQUE.floatValue ()) + style += Font.ITALIC; + } + + if (attribs.containsKey (TextAttribute.SIZE)) + { + Float sz = (Float) attribs.get (TextAttribute.SIZE); + size = sz.floatValue (); + + // Pango doesn't accept 0 as a font size. + if (size < 1) + size = 1; + } + else + size = 12; + + if (attribs.containsKey (TextAttribute.TRANSFORM)) + { + TransformAttribute ta = (TransformAttribute) + attribs.get(TextAttribute.TRANSFORM); + trans = ta.getTransform (); + } + + setStandardAttributes (name, family, style, size, trans); + } + + protected void getStandardAttributes (Map attrs) + { + copyFamilyToAttrs (this.familyName, attrs); + copySizeToAttrs (this.size, attrs); + copyStyleToAttrs (this.style, attrs); + copyTransformToAttrs (this.transform, attrs); + } + + + /* Begin public API */ + + public ClasspathFontPeer (String name, Map attrs) + { + setStandardAttributes (name, attrs); + } + + public ClasspathFontPeer (String name, int style, int size) + { + setStandardAttributes (name, (String)null, style, + (float)size, (AffineTransform)null); + } + + /** + * Implementation of {@link Font#getName} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public String getName (Font font) + { + return logicalName; + } + + /** + * Implementation of {@link Font#getFamily()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public String getFamily (Font font) + { + return familyName; + } + + /** + * Implementation of {@link Font#getFamily(Locale)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public String getFamily (Font font, Locale lc) + { + return familyName; + } + + /** + * Implementation of {@link Font#getFontName()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public String getFontName (Font font) + { + return faceName; + } + + /** + * Implementation of {@link Font#getFontName(Locale)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public String getFontName (Font font, Locale lc) + { + return faceName; + } + + /** + * Implementation of {@link Font#getSize} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public float getSize (Font font) + { + return size; + } + + /** + * Implementation of {@link Font#isPlain} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public boolean isPlain (Font font) + { + return style == Font.PLAIN; + } + + /** + * Implementation of {@link Font#isBold} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public boolean isBold (Font font) + { + return ((style & Font.BOLD) == Font.BOLD); + } + + /** + * Implementation of {@link Font#isItalic} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public boolean isItalic (Font font) + { + return ((style & Font.ITALIC) == Font.ITALIC); + } + + /** + * Implementation of {@link Font#deriveFont(int, float)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public Font deriveFont (Font font, int style, float size) + { + Map attrs = new HashMap (); + getStandardAttributes (attrs); + copyStyleToAttrs (style, attrs); + copySizeToAttrs (size, attrs); + return tk().getFont (logicalName, attrs); + } + + /** + * Implementation of {@link Font#deriveFont(float)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public Font deriveFont (Font font, float size) + { + Map attrs = new HashMap (); + getStandardAttributes (attrs); + copySizeToAttrs (size, attrs); + return tk().getFont (logicalName, attrs); + } + + /** + * Implementation of {@link Font#deriveFont(int)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public Font deriveFont (Font font, int style) + { + Map attrs = new HashMap (); + getStandardAttributes (attrs); + copyStyleToAttrs (style, attrs); + return tk().getFont (logicalName, attrs); + } + + /** + * Implementation of {@link Font#deriveFont(int, AffineTransform)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public Font deriveFont (Font font, int style, AffineTransform t) + { + Map attrs = new HashMap (); + getStandardAttributes (attrs); + copyStyleToAttrs (style, attrs); + copyTransformToAttrs (t, attrs); + return tk().getFont (logicalName, attrs); + } + + /** + * Implementation of {@link Font#deriveFont(AffineTransform)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public Font deriveFont (Font font, AffineTransform t) + { + Map attrs = new HashMap (); + getStandardAttributes (attrs); + copyTransformToAttrs (t, attrs); + return tk().getFont (logicalName, attrs); + } + + /** + * Implementation of {@link Font#deriveFont(Map)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public Font deriveFont (Font font, Map attrs) + { + return tk().getFont (logicalName, attrs); + } + + /** + * Implementation of {@link Font#getAttributes()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public Map getAttributes (Font font) + { + HashMap h = new HashMap (); + getStandardAttributes (h); + return h; + } + + /** + * Implementation of {@link Font#getAvailableAttributes()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public AttributedCharacterIterator.Attribute[] getAvailableAttributes(Font font) + { + AttributedCharacterIterator.Attribute a[] = + new AttributedCharacterIterator.Attribute[5]; + a[0] = TextAttribute.FAMILY; + a[1] = TextAttribute.SIZE; + a[2] = TextAttribute.POSTURE; + a[3] = TextAttribute.WEIGHT; + a[4] = TextAttribute.TRANSFORM; + return a; + } + + /** + * Implementation of {@link Font#getTransform()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public AffineTransform getTransform (Font font) + { + if (transform == null) + transform = new AffineTransform (); + return transform; + } + + /** + * Implementation of {@link Font#isTransformed()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public boolean isTransformed (Font font) + { + return ! transform.isIdentity (); + } + + /** + * Implementation of {@link Font#getItalicAngle()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public float getItalicAngle (Font font) + { + if ((style & Font.ITALIC) == Font.ITALIC) + return TextAttribute.POSTURE_OBLIQUE.floatValue (); + else + return TextAttribute.POSTURE_REGULAR.floatValue (); + } + + + /** + * Implementation of {@link Font#getStyle()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public int getStyle (Font font) + { + return style; + } + + + + + /* Remaining methods are abstract */ + + /** + * Implementation of {@link Font#canDisplay(char)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract boolean canDisplay (Font font, char c); + + /** + * Implementation of {@link Font#canDisplay(String)}, + * {@link Font#canDisplay(char [], int, int)}, and + * {@link Font#canDisplay(CharacterIterator, int, int)}. + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit); + + + /** + * Returns the name of this font face inside the family, for example + * <i>“Light”</i>. + * + * <p>This method is currently not used by {@link Font}. However, + * this name would be needed by any serious desktop publishing + * application. + * + * @param font the font whose sub-family name is requested. + * + * @param locale the locale for which to localize the name. If + * <code>locale</code> is <code>null</code>, the returned name is + * localized to the user’s default locale. + * + * @return the name of the face inside its family, or + * <code>null</code> if the font does not provide a sub-family name. + */ + + public abstract String getSubFamilyName (Font font, Locale locale); + + + /** + * Implementation of {@link Font#getPSName()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract String getPostScriptName (Font font); + + + /** + * Implementation of {@link Font#getNumGlyphs()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract int getNumGlyphs (Font font); + + + /** + * Implementation of {@link Font#getMissingGlyphCode()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract int getMissingGlyphCode (Font font); + + + /** + * Implementation of {@link Font#getBaselineFor(char)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract byte getBaselineFor (Font font, char c); + + + /** + * Returns a name for the specified glyph. This is useful for + * generating PostScript or PDF files that embed some glyphs of a + * font. If the implementation follows glyph naming conventions + * specified by Adobe, search engines can extract the original text + * from the generated PostScript and PDF files. + * + * <p>This method is currently not used by GNU Classpath. However, + * it would be very useful for someone wishing to write a good + * PostScript or PDF stream provider for the + * <code>javax.print</code> package. + * + * <p><b>Names are not unique:</b> Under some rare circumstances, + * the same name can be returned for different glyphs. It is + * therefore recommended that printer drivers check whether the same + * name has already been returned for antoher glyph, and make the + * name unique by adding the string ".alt" followed by the glyph + * index.</p> + * + * <p>This situation would occur for an OpenType or TrueType font + * that has a <code>post</code> table of format 3 and provides a + * mapping from glyph IDs to Unicode sequences through a + * <code>Zapf</code> table. If the same sequence of Unicode + * codepoints leads to different glyphs (depending on contextual + * position, for example, or on typographic sophistication level), + * the same name would get synthesized for those glyphs. To avoid + * this, the font peer would have to go through the names of all + * glyphs, which would make this operation very inefficient with + * large fonts. + * + * @param font the font containing the glyph whose name is + * requested. + * + * @param glyphIndex the glyph whose name the caller wants to + * retrieve. + * + * @return the glyph name, or <code>null</code> if a font does not + * provide glyph names. + */ + + public abstract String getGlyphName (Font font, int glyphIndex); + + + /** + * Implementation of {@link + * Font#createGlyphVector(FontRenderContext, String)}, {@link + * Font#createGlyphVector(FontRenderContext, char[])}, and {@link + * Font#createGlyphVector(FontRenderContext, CharacterIterator)}. + * + * @param font the font object that the created GlyphVector will return + * when it gets asked for its font. This argument is needed because the + * public API of {@link GlyphVector} works with {@link java.awt.Font}, + * not with font peers. + */ + + public abstract GlyphVector createGlyphVector (Font font, + FontRenderContext frc, + CharacterIterator ci); + + + /** + * Implementation of {@link Font#createGlyphVector(FontRenderContext, + * int[])}. + * + * @param font the font object that the created GlyphVector will return + * when it gets asked for its font. This argument is needed because the + * public API of {@link GlyphVector} works with {@link java.awt.Font}, + * not with font peers. + */ + + public abstract GlyphVector createGlyphVector (Font font, + FontRenderContext ctx, + int[] glyphCodes); + + + /** + * Implementation of {@link Font#layoutGlyphVector(FontRenderContext, + * char[], int, int, int)}. + * + * @param font the font object that the created GlyphVector will return + * when it gets asked for its font. This argument is needed because the + * public API of {@link GlyphVector} works with {@link java.awt.Font}, + * not with font peers. + */ + + public abstract GlyphVector layoutGlyphVector (Font font, + FontRenderContext frc, + char[] chars, int start, + int limit, int flags); + + + /** + * Implementation of {@link Font#getFontMetrics()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract FontMetrics getFontMetrics (Font font); + + + /** + * Implementation of {@link Font#hasUniformLineMetrics()} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract boolean hasUniformLineMetrics (Font font); + + + /** + * Implementation of {@link Font#getLineMetrics(CharacterIterator, int, + * int, FontRenderContext)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract LineMetrics getLineMetrics (Font font, + CharacterIterator ci, + int begin, int limit, + FontRenderContext rc); + + /** + * Implementation of {@link Font#getMaxCharBounds(FontRenderContext)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract Rectangle2D getMaxCharBounds (Font font, + FontRenderContext rc); + + /** + * Implementation of {@link Font#getStringBounds(CharacterIterator, int, + * int, FontRenderContext)} + * + * @param font the font this peer is being called from. This may be + * useful if you are sharing peers between Font objects. Otherwise it may + * be ignored. + */ + + public abstract Rectangle2D getStringBounds (Font font, + CharacterIterator ci, + int begin, int limit, + FontRenderContext frc); + +} diff --git a/libjava/classpath/gnu/java/awt/peer/ClasspathTextLayoutPeer.java b/libjava/classpath/gnu/java/awt/peer/ClasspathTextLayoutPeer.java new file mode 100644 index 0000000..70df2ef --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/ClasspathTextLayoutPeer.java @@ -0,0 +1,104 @@ +/* ClasspathTextLayoutPeer.java + Copyright (C) 2003 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; + +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.font.TextHitInfo; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; + +/** + * @author Graydon Hoare + */ + +public interface ClasspathTextLayoutPeer +{ + TextHitInfo getStrongCaret (TextHitInfo hit1, + TextHitInfo hit2); + + void draw (Graphics2D g2, float x, float y); + + byte getBaseline (); + + boolean isLeftToRight (); + boolean isVertical (); + + float getAdvance (); + float getAscent (); + float getDescent (); + float getLeading (); + + int getCharacterCount (); + byte getCharacterLevel (int index); + + float[] getBaselineOffsets (); + Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint); + Rectangle2D getBounds (); + + float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds); + Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds); + Shape[] getCaretShapes (int offset, Rectangle2D bounds, + TextLayout.CaretPolicy policy); + + Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint, + Rectangle2D bounds); + int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint, + TextHitInfo secondEndpoint); + + TextHitInfo getNextLeftHit (int offset, TextLayout.CaretPolicy policy); + TextHitInfo getNextRightHit (int offset, TextLayout.CaretPolicy policy); + TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds); + TextHitInfo getVisualOtherHit (TextHitInfo hit); + + float getVisibleAdvance (); + Shape getOutline (AffineTransform tx); + Shape getVisualHighlightShape (TextHitInfo firstEndpoint, + TextHitInfo secondEndpoint, + Rectangle2D bounds); + + TextLayout getJustifiedLayout (float justificationWidth); + void handleJustify (float justificationWidth); + + Object clone (); + int hashCode (); + boolean equals (ClasspathTextLayoutPeer tl); + String toString (); +} diff --git a/libjava/classpath/gnu/java/awt/peer/EmbeddedWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/EmbeddedWindowPeer.java new file mode 100644 index 0000000..4c64a1d --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/EmbeddedWindowPeer.java @@ -0,0 +1,47 @@ +/* EmbeddedWindowPeer.java -- Interface for window peers that may be + embedded into other applications + Copyright (C) 2003 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; + +import java.awt.peer.FramePeer; + +public interface EmbeddedWindowPeer extends FramePeer +{ + void embed (long handle); +} diff --git a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java new file mode 100644 index 0000000..3bcaebc --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java @@ -0,0 +1,298 @@ +/* GLightweightPeer.java -- + Copyright (C) 2003, 2004 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; + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.BufferCapabilities; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.event.PaintEvent; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.image.VolatileImage; +import java.awt.peer.ContainerPeer; +import java.awt.peer.LightweightPeer; + +/* + * Another possible implementation strategy for lightweight peers is + * to make GLightweightPeer a placeholder class that implements + * LightweightPeer. Then the Component and Container classes could + * identify a peer as lightweight and handle it specially. The + * current approach is probably more clear but less efficient. + */ + +/** + * A stub class that implements the ComponentPeer and ContainerPeer + * interfaces using callbacks into the Component and Container + * classes. GLightweightPeer allows the Component and Container + * classes to treat lightweight and heavyweight peers in the same way. + * + * Lightweight components are painted directly onto their parent + * containers through an Image object provided by the toolkit. + */ +public class GLightweightPeer + implements LightweightPeer, ContainerPeer +{ + private Component comp; + + private Insets containerInsets; + + public GLightweightPeer(Component comp) + { + this.comp = comp; + } + + // -------- java.awt.peer.ContainerPeer implementation: + + public Insets insets() + { + return getInsets (); + } + + public Insets getInsets() + { + if (containerInsets == null) + containerInsets = new Insets (0,0,0,0); + return containerInsets; + } + + public void beginValidate() + { + } + + public void endValidate() + { + } + + public void beginLayout() + { + } + + public void endLayout() + { + } + + public boolean isPaintPending() + { + return false; + } + + // -------- java.awt.peer.ComponentPeer implementation: + + public int checkImage(Image img, int width, int height, ImageObserver o) + { + return comp.getToolkit().checkImage(img, width, height, o); + } + + public Image createImage(ImageProducer prod) + { + return comp.getToolkit().createImage(prod); + } + + /* This method is not called. */ + public Image createImage(int width, int height) + { + return null; + } + + public void disable() {} + + public void dispose() {} + + public void enable() {} + + public GraphicsConfiguration getGraphicsConfiguration() + { + return null; + } + + public FontMetrics getFontMetrics(Font f) + { + return comp.getToolkit().getFontMetrics(f); + } + + /* Returning null here tells the Component object that called us to + * use its parent's Graphics. */ + public Graphics getGraphics() + { + return null; + } + + public Point getLocationOnScreen() + { + Point parentLocation = comp.getParent().getLocationOnScreen(); + return new Point (parentLocation.x + comp.getX(), + parentLocation.y + comp.getY()); + } + + public Dimension getMinimumSize() + { + return new Dimension(comp.getWidth(), comp.getHeight()); + } + + /* A lightweight component's preferred size is equivalent to its + * Component width and height values. */ + public Dimension getPreferredSize() + { + return new Dimension(comp.getWidth(), comp.getHeight()); + } + + /* Returning null here tells the Component object that called us to + * use its parent's Toolkit. */ + public Toolkit getToolkit() + { + return null; + } + + public void handleEvent(AWTEvent e) {} + + public void hide() {} + + public boolean isFocusable() + { + return false; + } + + public boolean isFocusTraversable() + { + return false; + } + + public Dimension minimumSize() + { + return getMinimumSize(); + } + + public Dimension preferredSize() + { + return getPreferredSize(); + } + + public void paint(Graphics graphics) {} + + public boolean prepareImage(Image img, int width, int height, + ImageObserver o) + { + return comp.getToolkit().prepareImage(img, width, height, o); + } + + public void print(Graphics graphics) {} + + public void repaint(long tm, int x, int y, int width, int height) {} + + public void requestFocus() {} + + public boolean requestFocus(Component source, boolean bool1, boolean bool2, long x) + { + return false; + } + + public void reshape(int x, int y, int width, int height) {} + + public void setBackground(Color color) {} + + public void setBounds(int x, int y, int width, int height) {} + + public void setCursor(Cursor cursor) {} + + public void setEnabled(boolean enabled) {} + + public void setEventMask(long eventMask) {} + + public void setFont(Font font) {} + + public void setForeground(Color color) {} + + public void setVisible(boolean visible) {} + + public void show() {} + + public ColorModel getColorModel () + { + return comp.getColorModel (); + } + + public boolean isObscured() + { + return false; + } + + public boolean canDetermineObscurity() + { + return false; + } + + public void coalescePaintEvent(PaintEvent e) { } + + public void updateCursorImmediately() { } + + public VolatileImage createVolatileImage(int width, int height) + { + return null; + } + + public boolean handlesWheelScrolling() + { + return false; + } + + public void createBuffers(int x, BufferCapabilities capabilities) + throws AWTException { } + + public Image getBackBuffer() + { + return null; + } + + public void flip(BufferCapabilities.FlipContents contents) { } + + public void destroyBuffers() { } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GThreadMutex.java b/libjava/classpath/gnu/java/awt/peer/gtk/GThreadMutex.java new file mode 100644 index 0000000..e73df9e --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GThreadMutex.java @@ -0,0 +1,109 @@ +/* GThreadMutex.java -- Implements a mutex object for glib's gthread + abstraction, for use with GNU Classpath's --portable-native-sync option. + This is used in gthread-jni.c + + Copyright (C) 2004 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; + +/** Implements a mutex object for glib's gthread + abstraction, for use with GNU Classpath's --portable-native-sync option. + This is used in gthread-jni.c. + + We use this object to implement the POSIX semantics for Mutexes. They are + needed are needed for the function vector that is passed to glib's + g_thread subpackage's initialization function. + + The GThreadMutex object itself serves as the Real Lock; if code has + entered the monitor for this GThreadMutex object (in Java language, if + it's synchronized on this object) then it holds the lock that this object + represents. + + @author Steven Augart + May, 2004 + + +*/ + +class GThreadMutex +{ + /** Might "lock" be locked? Is anyone waiting + to get that lock? How long is the queue? + + If zero, nobody holds a lock on this GThreadMutex object, and nobody is + trying to get one. Before someone attempts to acquire a lock on this + object, they must increment potentialLockers. After they release their + lock on this object, they must decrement potentialLockers. + + Access to this field is guarded by synchronizing on the object + <code>lockForPotentialLockers</code>. + + After construction, we only access this field via JNI. + */ + volatile int potentialLockers; + + /** An object to synchronize to if you want to examine or modify the + <code>potentialLockers</code> field. Only hold this lock for brief + moments, just long enough to check or set the value of + <code>lockForPotentialLockers</code>. + + We use this representation so that g_thread_mutex_trylock() will work + with the POSIX semantics. This is the only case in which you ever hold a + lock on <code>lockForPotentialLockers</code> while trying to get another + lock -- if you are the mutex_trylock() implementation, and you have just + checked that <code>potentialLockers</code> has the value zero. In that + case, mutex_trylock() holds the lock on lockForPotentialLockers so that + another thread calling mutex_trylock() or mutex_lock() won't increment + potentialLockers after we've checked it and before we've gained the lock + on the POSIX mutex. Of course, in that case the operation of gaining + the POSIX lock itself will succeed immediately, and once it has + succeeded, trylock releases lockForPotentialLockers right away, + incremented to 1 (one). + + After construction, we only access this field via JNI. + */ + Object lockForPotentialLockers; + + GThreadMutex() + { + potentialLockers = 0; + lockForPotentialLockers = new Object(); + } +} +// Local Variables: +// c-file-style: "gnu" +// End: diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java b/libjava/classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java new file mode 100644 index 0000000..9a1b8e3 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java @@ -0,0 +1,303 @@ +/* GThreadNativeMethodRunner.java -- Implements pthread_create(), under + glib's gthread abstraction, for use with GNU Classpath's + --portable-native-sync option. + This is used by gthread-jni.c + + Copyright (C) 2004, 2005 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.lang.ref.WeakReference; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** Implements pthread_create(), under glib's gthread abstraction, for use + with GNU Classpath's --portable-native-sync option. This is used in + gthread-jni.c + + Also implements a registry for threads, mapping Thread objects to small + integers. The registry uses weak references for threads that aren't + joinable, so that they will be garbage collected. + + There are a number of possible alternative implementations. + + + The rest of this comment consists of an answer to a question that was + raised on the commit-classpath mailing list: + + Mark Wielaard wrote: + + > Can't we assume that jobject and gpointer are both (void *) so we don't + > need the int <-> Thread (global jobject ref) mapping? + > Maybe there are platforms where jobject and gpointer aren't the same, + > but I guess that is pretty unlikely. + + + I agree with you on the pointer size issues. A gpointer is a void *, so + it's certainly guaranteed to be at least as large as any other + pointer. And a jobject is implicitly an opaque pointer (in Jikes RVM, we + use small integers, but we coerce them into the representation of a + pointer). + + The int <==> Thread mapping addresses a different issue. I realize that I + did not document this properly (two and a half lines in thread_create), + and the point is subtle (at least to me; took me a while to figure out). + + The int => Thread mapping always returns jobjects that are local + references, not global ones. This is because Thread objects need to be + able to go away and be garbage collected after the thread they refer to + has died. + + If we keep a global object reference to a thread, then when do we delete + that global object reference? We have an answer in the case of GThread + objects that were explicitly created with the joinable attribute. It is + safe for us to maintain a global reference to any joinable thread, since + the joinable thread must linger (even if only in a zombie state) + until it's explicitly joined via a g_thread_join() call. The global ref + could be cleaned up at that point too. + + However, in the case of GThreads that were created non-joinable by + g_thread_create(), and in the case of Java threads that were created + within pure Java code (not via g_thread_create()), we don't want them to + linger forever, and there is no way to tell when the last reference + to such threads needs to expire. In the case of this application -- AWT + with GTK peers -- it would probably be safe anyway, since there are not + very many threads we create, but I was going for correctness even in the + case of long-running programs that might set up and tear down AWT + interfaces many times. + + So, I duplicated the POSIX thread-ID semantics. The thread ID of a + non-joinable thread remains valid as long as that thread is still alive. + Once that thread dies, the old thread ID may be reused at any moment. And + that's why the array indexed by thread ID numbers is an array of weak + references. + + That's also why the int => Thread jobject mapping function always returns + local references, since global references would lock the Thread in memory + forever. + + I would dearly love there to be a cleaner solution. I dislike the + repeated dips from C code into Java that are necessary to look up thread + ID numbers. If anyone can think of one, I'm all ears. +*/ + +class GThreadNativeMethodRunner + extends Thread +{ + /** The C function pointer that was passed to g_thread_create(). + Specifically, this the numeric address of an object of + C type "void *(*funcPtr)(void *funcArg)". + */ + private final long funcPtr; + + /** The argument for the function "funcPtr(funcArg)". */ + private final long funcArg; + + GThreadNativeMethodRunner(long funcPtr, long funcArg, boolean joinable) + { + this.funcPtr = funcPtr; + this.funcArg = funcArg; + + if (joinable) + registerSelfJoinable(); + } + + public void run() + { + nativeRun(funcPtr, funcArg); + } + + private native void nativeRun(long funcPtr, long funcArg); + + /** THREADS is an array of threads, indexed by thread ID codes. Not sure + whether this is the "best" approach but it does make it O(1) to look up a + thread by its ID. + + Zero is a valid thread ID code. Any negative number is invalid. + + Possible future fixes (TODO?) + + - The THREADS array will only grow. probably not a problem. + But we could keep count when nulling entries and shrink when we have + lots of nulls at the end. Probably not worth it. --mjw + + - Could make this a set of Object; see the comment on "joinable" below. + + The initial size of 17 is just a starting point. Any number will do, + including zero. + */ + private static WeakReference[] threads = new WeakReference[17]; + + /** Used by threadToThreadID, below. Returns the registration number of + the newly-registered thread. + */ + private static synchronized int registerThread(Thread t) + { + int i; + + for (i = 0; i < threads.length; ++i) + { + WeakReference ref = threads[i]; + if (ref == null) + break; // found an empty spot. + } + + if (i == threads.length) + { + /* expand the array */ + WeakReference[] bigger = new WeakReference[threads.length * 2]; + System.arraycopy(threads, 0, bigger, 0, threads.length); + threads = bigger; + } + + threads[i] = new WeakReference(t); + + return i; + } + + /** Look up the Thread ID # for a Thread. Assign a Thread ID # if none + exists. This is a general routine for handling all threads, including + the VM's main thread, if appropriate. + + + Runs in O(n/2) time. + + We can't just issue a threadID upon thread creation. If we were to do + that, not all threads would have a threadID, because not all threads + are launched by GThreadNativeMethodRunner. + */ + static synchronized int threadToThreadID(Thread t) + { + for (int i = 0; i < threads.length; ++i ) + { + if (threads[i] == null) + continue; + Thread referent = (Thread) threads[i].get(); + if (referent == null) + { + threads[i] = null; // Purge the dead WeakReference. + continue; + } + if (referent.equals(t)) + return i; + } // for() + + /* No match found. */ + return registerThread(t); + } + + /** @param threadID Must be a non-negative integer. + + Used to return null if the thread number was out of range or if + the thread was unregistered. Now we throw an exception. + + Possible Alternative Interface: We could go back to returning null in + some sort of check-free mode, so code that calls this function must + be prepared to get null. + */ + static Thread threadIDToThread(int threadID) + throws IllegalArgumentException + { + if (threadID < 0) + throw new IllegalArgumentException("Received a negative threadID, " + + threadID); + if (threadID >= threads.length) + throw new IllegalArgumentException("Received a threadID (" + threadID + + ") higher than was" + + " ever issued"); + + /* Note: if the user is using a stale reference, things will just + break. We might end up getting a different thread than the one + expected. + + TODO: Add an error-checking mode where the user's problems with threads + are announced. For instance, if the user asks for the thread + associated with a threadID that was never issued, we could print a + warning or even abort. + + TODO: Consider optionally disabling all of the error-checking we + already have; it probably slows down the implementation. We could + just return NULL. This is just the reverse of the above TODO item. + */ + + WeakReference threadRef = threads[threadID]; + + if (threadRef == null) + throw new IllegalArgumentException("Asked to look up a stale or unissued" + + "threadID (" + threadID + ")" ); + + + Thread referent = (Thread) threadRef.get(); + if (referent == null) + throw new IllegalArgumentException ("Asked to look up a stale threadID (" + + threadID + ")"); + return referent; + } + + /** Joinable threads need a hard reference, so that they won't go away when + they die. That is because their thread IDs need to stay valid until the + thread is joined via thread_join(threadID). Joinable threads have to be + explicitly joined before they are allowed to go away completely. + + Possible Alternative Implementation: Eliminate the Joinable set. When + calling getThreadIDFromThread() you know whether or not the thread + is joinable. So just store the Thread itself in the threads array? + Make that array an Object array and check with instanceof. This + looks cleaner and more robust to me and it saves a native -> Java + call. But instanceof might be expensive. --mjw + */ + private static final Set joinable = + Collections.synchronizedSet(new HashSet()); + + /** Only called from the constructor. */ + private void registerSelfJoinable() + { + joinable.add(this); + } + + /** This method is only called from JNI, and only after we have succeeded in + a thread_join() operation. */ + static void deRegisterJoinable(Thread thread) + { + joinable.remove(thread); + } +} + +// Local Variables: +// c-file-style: "gnu" +// End: diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontMetrics.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontMetrics.java new file mode 100644 index 0000000..7a439e8 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontMetrics.java @@ -0,0 +1,134 @@ +/* GdkFontMetrics.java + Copyright (C) 1999, 2002, 2004 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.ClasspathToolkit; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Toolkit; + +public class GdkFontMetrics extends FontMetrics +{ + + private int[] font_metrics; + GdkFontPeer peer; + + static final int FONT_METRICS_ASCENT = 0; + static final int FONT_METRICS_MAX_ASCENT = 1; + static final int FONT_METRICS_DESCENT = 2; + static final int FONT_METRICS_MAX_DESCENT = 3; + static final int FONT_METRICS_MAX_ADVANCE = 4; + + static final int TEXT_METRICS_X_BEARING = 0; + static final int TEXT_METRICS_Y_BEARING = 1; + static final int TEXT_METRICS_WIDTH = 2; + static final int TEXT_METRICS_HEIGHT = 3; + static final int TEXT_METRICS_X_ADVANCE = 4; + static final int TEXT_METRICS_Y_ADVANCE = 5; + + + public GdkFontMetrics (Font font) + { + super (font.getPeer() instanceof GdkFontPeer + ? font + : ((ClasspathToolkit)(Toolkit.getDefaultToolkit ())) + .getFont (font.getName(), font.getAttributes ())); + + peer = (GdkFontPeer) this.font.getPeer(); + + font_metrics = new int[5]; + double [] hires = new double[5]; + peer.getFontMetrics (hires); + for (int i = 0; i < 5; ++i) + font_metrics[i] = (int) hires[i]; + } + + public int stringWidth (String str) + { + double [] hires = new double[6]; + peer.getTextMetrics(str, hires); + return (int) hires [TEXT_METRICS_WIDTH]; + } + + public int charWidth (char ch) + { + return stringWidth (new String (new char[] { ch })); + } + + public int charsWidth (char data[], int off, int len) + { + return stringWidth (new String (data, off, len)); + } + + /* + Sun's Motif implementation always returns 0 or 1 here (???), but + going by the X11 man pages, it seems as though we should return + font.ascent + font.descent. + */ + public int getLeading () + { + return 1; + } + + public int getAscent () + { + return font_metrics[FONT_METRICS_ASCENT]; + } + + public int getMaxAscent () + { + return font_metrics[FONT_METRICS_MAX_ASCENT]; + } + + public int getDescent () + { + return font_metrics[FONT_METRICS_DESCENT]; + } + + public int getMaxDescent () + { + return font_metrics[FONT_METRICS_MAX_DESCENT]; + } + + public int getMaxAdvance () + { + return font_metrics[FONT_METRICS_MAX_ADVANCE]; + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java new file mode 100644 index 0000000..c6d42b3 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java @@ -0,0 +1,307 @@ +/* GdkFontPeer.java -- Implements FontPeer with GTK+ + Copyright (C) 1999, 2004, 2005 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.classpath.Configuration; +import gnu.java.awt.peer.ClasspathFontPeer; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.geom.Rectangle2D; +import java.text.CharacterIterator; +import java.text.StringCharacterIterator; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +public class GdkFontPeer extends ClasspathFontPeer +{ + static native void initStaticState(); + private final int native_state = GtkGenericPeer.getUniqueInteger (); + private static ResourceBundle bundle; + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("gtkpeer"); + } + + initStaticState (); + + try + { + bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font"); + } + catch (Throwable ignored) + { + bundle = null; + } + } + + private native void initState (); + private native void dispose (); + private native void setFont (String family, int style, int size, boolean useGraphics2D); + + native void getFontMetrics(double [] metrics); + native void getTextMetrics(String str, double [] metrics); + + protected void finalize () + { + if (GtkToolkit.useGraphics2D ()) + GdkGraphics2D.releasePeerGraphicsResource(this); + dispose (); + } + + /* + * Helpers for the 3-way overloading that this class seems to suffer + * from. Remove them if you feel like they're a performance bottleneck, + * for the time being I prefer my code not be written and debugged in + * triplicate. + */ + + private String buildString(CharacterIterator iter) + { + StringBuffer sb = new StringBuffer(); + for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) + sb.append(c); + return sb.toString(); + } + + private String buildString(CharacterIterator iter, int begin, int limit) + { + StringBuffer sb = new StringBuffer(); + int i = 0; + for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next(), i++) + { + if (begin <= i) + sb.append(c); + if (limit <= i) + break; + } + return sb.toString(); + } + + private String buildString(char[] chars, int begin, int limit) + { + return new String(chars, begin, limit - begin); + } + + /* Public API */ + + public GdkFontPeer (String name, int style) + { + // All fonts get a default size of 12 if size is not specified. + this(name, style, 12); + } + + public GdkFontPeer (String name, int style, int size) + { + super(name, style, size); + initState (); + setFont (this.familyName, this.style, (int)this.size, + GtkToolkit.useGraphics2D()); + } + + public GdkFontPeer (String name, Map attributes) + { + super(name, attributes); + initState (); + setFont (this.familyName, this.style, (int)this.size, + GtkToolkit.useGraphics2D()); + } + + public String getSubFamilyName(Font font, Locale locale) + { + return null; + } + + public String getPostScriptName(Font font) + { + return null; + } + + public boolean canDisplay (Font font, char c) + { + // FIXME: inquire with pango + return true; + } + + public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit) + { + // FIXME: inquire with pango + return -1; + } + + private native GdkGlyphVector getGlyphVector(String txt, + Font f, + FontRenderContext ctx); + + public GlyphVector createGlyphVector (Font font, + FontRenderContext ctx, + CharacterIterator i) + { + return getGlyphVector(buildString (i), font, ctx); + } + + public GlyphVector createGlyphVector (Font font, + FontRenderContext ctx, + int[] glyphCodes) + { + return null; + // return new GdkGlyphVector (font, this, ctx, glyphCodes); + } + + public byte getBaselineFor (Font font, char c) + { + throw new UnsupportedOperationException (); + } + + protected class GdkFontLineMetrics extends LineMetrics + { + FontMetrics fm; + int nchars; + + public GdkFontLineMetrics (FontMetrics m, int n) + { + fm = m; + nchars = n; + } + + public float getAscent() + { + return (float) fm.getAscent (); + } + + public int getBaselineIndex() + { + return Font.ROMAN_BASELINE; + } + + public float[] getBaselineOffsets() + { + return new float[3]; + } + + public float getDescent() + { + return (float) fm.getDescent (); + } + + public float getHeight() + { + return (float) fm.getHeight (); + } + + public float getLeading() { return 0.f; } + public int getNumChars() { return nchars; } + public float getStrikethroughOffset() { return 0.f; } + public float getStrikethroughThickness() { return 0.f; } + public float getUnderlineOffset() { return 0.f; } + public float getUnderlineThickness() { return 0.f; } + + } + + public LineMetrics getLineMetrics (Font font, CharacterIterator ci, + int begin, int limit, FontRenderContext rc) + { + return new GdkFontLineMetrics (getFontMetrics (font), limit - begin); + } + + public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc) + { + throw new UnsupportedOperationException (); + } + + public int getMissingGlyphCode (Font font) + { + throw new UnsupportedOperationException (); + } + + public String getGlyphName (Font font, int glyphIndex) + { + throw new UnsupportedOperationException (); + } + + public int getNumGlyphs (Font font) + { + throw new UnsupportedOperationException (); + } + + public Rectangle2D getStringBounds (Font font, CharacterIterator ci, + int begin, int limit, FontRenderContext frc) + { + GdkGlyphVector gv = getGlyphVector(buildString (ci, begin, limit), font, frc); + return gv.getVisualBounds(); + } + + public boolean hasUniformLineMetrics (Font font) + { + return true; + } + + public GlyphVector layoutGlyphVector (Font font, FontRenderContext frc, + char[] chars, int start, int limit, + int flags) + { + int nchars = (limit - start) + 1; + char[] nc = new char[nchars]; + + for (int i = 0; i < nchars; ++i) + nc[i] = chars[start + i]; + + return createGlyphVector (font, frc, + new StringCharacterIterator (new String (nc))); + } + + public LineMetrics getLineMetrics (Font font, String str, + FontRenderContext frc) + { + return new GdkFontLineMetrics (getFontMetrics (font), str.length ()); + } + + public FontMetrics getFontMetrics (Font font) + { + return new GdkFontMetrics (font); + } + +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGlyphVector.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGlyphVector.java new file mode 100644 index 0000000..f0ddea4 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGlyphVector.java @@ -0,0 +1,359 @@ +/* GdkGlyphVector.java -- Glyph vector object + Copyright (C) 2003, 2004, 2005 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.Font; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphJustificationInfo; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +public class GdkGlyphVector extends GlyphVector +{ + + /* We use a simple representation for glyph vectors here. Glyph i + * consumes 8 doubles: + * + * logical x: extents[ 10*i ] + * logical y: extents[ 10*i + 1 ] + * logical width: extents[ 10*i + 2 ] + * logical height: extents[ 10*i + 3 ] + * + * visual x: extents[ 10*i + 4 ] + * visual y: extents[ 10*i + 5 ] + * visual width: extents[ 10*i + 6 ] + * visual height: extents[ 10*i + 7 ] + * + * origin pos x: extents[ 10*i + 8 ] + * origin pos y: extents[ 10*i + 9 ] + * + * as well as one int, code[i], representing the glyph code in the font. + */ + + double [] extents; + int [] codes; + + Font font; + FontRenderContext fontRenderContext; + + Rectangle2D allLogical; + Rectangle2D allVisual; + + public GdkGlyphVector(double[] extents, int[] codes, Font font, FontRenderContext frc) + { + this.extents = extents; + this.codes = codes; + this.font = font; + this.fontRenderContext = frc; + + allLogical = new Rectangle2D.Double(); + allVisual = new Rectangle2D.Double(); + + for (int i = 0; i < codes.length; ++i) + { + allLogical.add (new Rectangle2D.Double(extents[10*i ] + extents[10*i + 8], + extents[10*i + 1] + extents[10*i + 9], + extents[10*i + 2], + extents[10*i + 3])); + + allVisual.add (new Rectangle2D.Double(extents[10*i + 4] + extents[10*i + 8], + extents[10*i + 5] + extents[10*i + 9], + extents[10*i + 6], + extents[10*i + 7])); + } + } + + /* + geometric notes: + + the FRC contains a mapping from points -> pixels. + + typographics points are typically 1/72 of an inch. + + pixel displays are often around 72 dpi. + + so the FRC can get away with using an identity transform on a screen, + often. behavior is documented by sun to fall back to an identity + transform if the internal transformation is null. + + coordinates coming up from pango are expressed as floats -- in device + space, so basically pixels-with-fractional-bits -- derived from their + storage format in pango (1024ths of pixels). + + it is not clear from the javadocs whether the results of methods like + getGlyphPositions ought to return coordinates in device space, or + "point" space, or what. for now I'm returning them in device space. + + */ + + public double[] getExtents() + { + return extents; + } + + public int[] getCodes() + { + return codes; + } + + public Font getFont () + { + return font; + } + + public FontRenderContext getFontRenderContext () + { + return fontRenderContext; + } + + public int getGlyphCharIndex (int glyphIndex) + { + // FIXME: currently pango does not provide glyph-by-glyph + // reverse mapping information, so we assume a broken 1:1 + // glyph model here. This is plainly wrong. + return glyphIndex; + } + + public int[] getGlyphCharIndices (int beginGlyphIndex, + int numEntries, + int[] codeReturn) + { + int ix[] = codeReturn; + if (ix == null) + ix = new int[numEntries]; + + for (int i = 0; i < numEntries; i++) + ix[i] = getGlyphCharIndex (beginGlyphIndex + i); + return ix; + } + + public int getGlyphCode (int glyphIndex) + { + return codes[glyphIndex]; + } + + public int[] getGlyphCodes (int beginGlyphIndex, int numEntries, + int[] codeReturn) + { + if (codeReturn == null) + codeReturn = new int[numEntries]; + + System.arraycopy(codes, beginGlyphIndex, codeReturn, 0, numEntries); + return codeReturn; + } + + public Shape getGlyphLogicalBounds (int i) + { + return new Rectangle2D.Double (extents[8*i], extents[8*i + 1], + extents[8*i + 2], extents[8*i + 3]); + } + + public GlyphMetrics getGlyphMetrics (int i) + { + // FIXME: pango does not yield vertical layout information at the + // moment. + + boolean is_horizontal = true; + double advanceX = extents[8*i + 2]; // "logical width" == advanceX + double advanceY = 0; + + return new GlyphMetrics (is_horizontal, + (float) advanceX, (float) advanceY, + (Rectangle2D) getGlyphVisualBounds(i), + GlyphMetrics.STANDARD); + } + + public Shape getGlyphOutline (int glyphIndex) + { + throw new UnsupportedOperationException (); + } + + public Shape getGlyphOutline (int glyphIndex, float x, float y) + { + throw new UnsupportedOperationException (); + } + + public Rectangle getGlyphPixelBounds (int i, + FontRenderContext renderFRC, + float x, float y) + { + return new Rectangle((int) x, (int) y, + (int) extents[8*i + 6], (int) extents[8*i + 7]); + } + + public Point2D getGlyphPosition (int i) + { + return new Point2D.Double (extents[10*i + 8], + extents[10*i + 9]); + } + + public float[] getGlyphPositions (int beginGlyphIndex, + int numEntries, + float[] positionReturn) + { + float fx[] = positionReturn; + if (fx == null) + fx = new float[numEntries * 2]; + + for (int i = 0; i < numEntries; ++i) + { + fx[2*i ] = (float) extents[10*i + 8]; + fx[2*i + 1] = (float) extents[10*i + 9]; + } + return fx; + } + + public AffineTransform getGlyphTransform (int glyphIndex) + { + // Glyphs don't have independent transforms in these simple glyph + // vectors; docs specify null is an ok return here. + return null; + } + + public Shape getGlyphVisualBounds (int i) + { + return new Rectangle2D.Double(extents[8*i + 4], extents[8*i + 5], + extents[8*i + 6], extents[8*i + 7]); + } + + public int getLayoutFlags () + { + return 0; + } + + public Rectangle2D getLogicalBounds () + { + return allLogical; + } + + public int getNumGlyphs () + { + return codes.length; + } + + public Shape getOutline () + { + throw new UnsupportedOperationException (); + } + + public Rectangle getPixelBounds (FontRenderContext renderFRC, + float x, float y) + { + return new Rectangle((int)x, + (int)y, + (int) allVisual.getWidth(), + (int) allVisual.getHeight()); + } + + public Rectangle2D getVisualBounds () + { + return allVisual; + } + + public void performDefaultLayout () + { + } + + public void setGlyphPosition (int i, Point2D newPos) + { + extents[8*i ] = newPos.getX(); + extents[8*i + 1] = newPos.getY(); + + extents[8*i + 4] = newPos.getX(); + extents[8*i + 5] = newPos.getY(); + } + + public void setGlyphTransform (int glyphIndex, + AffineTransform newTX) + { + // not yet.. maybe not ever? + throw new UnsupportedOperationException (); + } + + public boolean equals(GlyphVector gv) + { + if (gv == null) + return false; + + if (! (gv instanceof GdkGlyphVector)) + return false; + + GdkGlyphVector ggv = (GdkGlyphVector) gv; + + if ((ggv.codes.length != this.codes.length) + || (ggv.extents.length != this.extents.length)) + return false; + + if ((ggv.font == null && this.font != null) + || (ggv.font != null && this.font == null) + || (!ggv.font.equals(this.font))) + return false; + + if ((ggv.fontRenderContext == null && this.fontRenderContext != null) + || (ggv.fontRenderContext != null && this.fontRenderContext == null) + || (!ggv.fontRenderContext.equals(this.fontRenderContext))) + return false; + + for (int i = 0; i < ggv.codes.length; ++i) + if (ggv.codes[i] != this.codes[i]) + return false; + + for (int i = 0; i < ggv.extents.length; ++i) + if (ggv.extents[i] != this.extents[i]) + return false; + + return true; + } + + public GlyphJustificationInfo getGlyphJustificationInfo(int idx) + { + throw new UnsupportedOperationException (); + } + + public Shape getOutline(float x, float y) + { + throw new UnsupportedOperationException (); + } + +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java new file mode 100644 index 0000000..a125be7 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java @@ -0,0 +1,388 @@ +/* GdkGraphics.java + Copyright (C) 1998, 1999, 2002, 2005 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.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.SystemColor; +import java.awt.image.ImageObserver; +import java.text.AttributedCharacterIterator; + +public class GdkGraphics extends Graphics +{ + private final int native_state = GtkGenericPeer.getUniqueInteger(); + + Color color, xorColor; + GtkComponentPeer component; + Font font; + Rectangle clip; + GtkImage image; + + int xOffset = 0; + int yOffset = 0; + + static final int GDK_COPY = 0, GDK_XOR = 2; + + native void initState (GtkComponentPeer component); + native void initState (int width, int height); + native void initFromImage (GtkImage image); + native void copyState (GdkGraphics g); + + GdkGraphics (GdkGraphics g) + { + color = g.color; + xorColor = g.xorColor; + font = g.font; + clip = new Rectangle (g.clip); + component = g.component; + + copyState (g); + } + + GdkGraphics (int width, int height) + { + initState (width, height); + color = Color.black; + clip = new Rectangle (0, 0, width, height); + font = new Font ("Dialog", Font.PLAIN, 12); + } + + GdkGraphics (GtkImage image) + { + this.image = image; + initFromImage (image); + color = Color.black; + clip = new Rectangle (0, 0, + image.getWidth(null), image.getHeight(null)); + font = new Font ("Dialog", Font.PLAIN, 12); + } + + GdkGraphics (GtkComponentPeer component) + { + this.component = component; + font = component.awtComponent.getFont (); + color = Color.black; + + if (component.isRealized ()) + initComponentGraphics (); + else + connectSignals (component); + } + + void initComponentGraphics () + { + initState (component); + color = component.awtComponent.getForeground (); + Dimension d = component.awtComponent.getSize (); + clip = new Rectangle (0, 0, d.width, d.height); + } + + native void connectSignals (GtkComponentPeer component); + + public native void clearRect(int x, int y, int width, int height); + + public void clipRect (int x, int y, int width, int height) + { + if (component != null && ! component.isRealized ()) + return; + + clip = clip.intersection (new Rectangle (x, y, width, height)); + setClipRectangle (clip.x, clip.y, clip.width, clip.height); + } + + public native void copyArea(int x, int y, int width, int height, + int dx, int dy); + + public Graphics create () + { + return new GdkGraphics (this); + } + + public native void dispose(); + + public boolean drawImage (Image img, int x, int y, + Color bgcolor, ImageObserver observer) + { + return drawImage(img, x, y, img.getWidth(null), img.getHeight(null), + bgcolor, observer); + } + + public boolean drawImage (Image img, int x, int y, ImageObserver observer) + { + return drawImage (img, x, y, null, observer); + } + + public boolean drawImage (Image img, int x, int y, int width, int height, + Color bgcolor, ImageObserver observer) + { + if (img instanceof GtkImage) + return ((GtkImage)img).drawImage (this, x, y, width, height, + bgcolor, observer); + else + return (new GtkImage(img.getSource())).drawImage (this, x, y, + width, height, + bgcolor, observer); + } + + public boolean drawImage (Image img, int x, int y, int width, int height, + ImageObserver observer) + { + return drawImage (img, x, y, width, height, null, observer); + } + + public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + Color bgcolor, ImageObserver observer) + { + if (img instanceof GtkImage) + return ((GtkImage)img).drawImage(this, dx1, dy1, dx2, dy2, + sx1, sy1, sx2, sy2, bgcolor, observer); + else + return (new GtkImage(img.getSource())).drawImage(this, dx1, dy1, + dx2, dy2, + sx1, sy1, sx2, sy2, + bgcolor, observer); + } + + public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + ImageObserver observer) + { + return drawImage (img, dx1, dy1, dx2, dy2, + sx1, sy1, sx2, sy2, + null, observer); + } + + public native void drawLine(int x1, int y1, int x2, int y2); + + public native void drawArc(int x, int y, int width, int height, + int startAngle, int arcAngle); + public native void fillArc(int x, int y, int width, int height, + int startAngle, int arcAngle); + public native void drawOval(int x, int y, int width, int height); + public native void fillOval(int x, int y, int width, int height); + + public native void drawPolygon(int[] xPoints, int[] yPoints, int nPoints); + public native void fillPolygon(int[] xPoints, int[] yPoints, int nPoints); + + public native void drawPolyline(int[] xPoints, int[] yPoints, int nPoints); + + public native void drawRect(int x, int y, int width, int height); + public native void fillRect(int x, int y, int width, int height); + + GdkFontPeer getFontPeer() + { + return (GdkFontPeer) getFont().getPeer(); + } + + native void drawString (GdkFontPeer f, String str, int x, int y); + public void drawString (String str, int x, int y) + { + drawString(getFontPeer(), str, x, y); + } + + + public void drawString (AttributedCharacterIterator ci, int x, int y) + { + throw new Error ("not implemented"); + } + + public void drawRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight) + { + if (arcWidth > width) + arcWidth = width; + if (arcHeight > height) + arcHeight = height; + + int xx = x + width - arcWidth; + int yy = y + height - arcHeight; + + drawArc (x, y, arcWidth, arcHeight, 90, 90); + drawArc (xx, y, arcWidth, arcHeight, 0, 90); + drawArc (xx, yy, arcWidth, arcHeight, 270, 90); + drawArc (x, yy, arcWidth, arcHeight, 180, 90); + + int y1 = y + arcHeight / 2; + int y2 = y + height - arcHeight / 2; + drawLine (x, y1, x, y2); + drawLine (x + width, y1, x + width, y2); + + int x1 = x + arcWidth / 2; + int x2 = x + width - arcWidth / 2; + drawLine (x1, y, x2, y); + drawLine (x1, y + height, x2, y + height); + } + + public void fillRoundRect (int x, int y, int width, int height, + int arcWidth, int arcHeight) + { + if (arcWidth > width) + arcWidth = width; + if (arcHeight > height) + arcHeight = height; + + int xx = x + width - arcWidth; + int yy = y + height - arcHeight; + + fillArc (x, y, arcWidth, arcHeight, 90, 90); + fillArc (xx, y, arcWidth, arcHeight, 0, 90); + fillArc (xx, yy, arcWidth, arcHeight, 270, 90); + fillArc (x, yy, arcWidth, arcHeight, 180, 90); + + fillRect (x, y + arcHeight / 2, width, height - arcHeight + 1); + fillRect (x + arcWidth / 2, y, width - arcWidth + 1, height); + } + + public Shape getClip () + { + return getClipBounds (); + } + + public Rectangle getClipBounds () + { + if (clip == null) + return null; + else + return clip.getBounds(); + } + + public Color getColor () + { + return color; + } + + public Font getFont () + { + return font; + } + + public FontMetrics getFontMetrics (Font font) + { + return new GdkFontMetrics (font); + } + + native void setClipRectangle (int x, int y, int width, int height); + + public void setClip (int x, int y, int width, int height) + { + if ((component != null && ! component.isRealized ()) + || clip == null) + return; + + clip.x = x; + clip.y = y; + clip.width = width; + clip.height = height; + + setClipRectangle (x, y, width, height); + } + + public void setClip (Rectangle clip) + { + setClip (clip.x, clip.y, clip.width, clip.height); + } + + public void setClip (Shape clip) + { + if (clip != null) + setClip(clip.getBounds()); + } + + private native void setFGColor(int red, int green, int blue); + + public void setColor (Color c) + { + if (c == null) + color = Color.BLACK; + else + color = c; + + if (xorColor == null) /* paint mode */ + setFGColor (color.getRed (), color.getGreen (), color.getBlue ()); + else /* xor mode */ + setFGColor (color.getRed () ^ xorColor.getRed (), + color.getGreen () ^ xorColor.getGreen (), + color.getBlue () ^ xorColor.getBlue ()); + } + + public void setFont (Font font) + { + this.font = font; + } + + native void setFunction (int gdk_func); + + public void setPaintMode () + { + xorColor = null; + + setFunction (GDK_COPY); + setFGColor (color.getRed (), color.getGreen (), color.getBlue ()); + } + + public void setXORMode (Color c) + { + xorColor = c; + + setFunction (GDK_XOR); + setFGColor (color.getRed () ^ xorColor.getRed (), + color.getGreen () ^ xorColor.getGreen (), + color.getBlue () ^ xorColor.getBlue ()); + } + + public native void translateNative(int x, int y); + + public void translate (int x, int y) + { + if (component != null && ! component.isRealized ()) + return; + + clip.x -= x; + clip.y -= y; + + translateNative (x, y); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java new file mode 100644 index 0000000..b820317 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java @@ -0,0 +1,1453 @@ +/* GdkGraphics2D.java -- + Copyright (C) 2003, 2004, 2005 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.classpath.Configuration; +import gnu.java.awt.ClasspathToolkit; + +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.TexturePaint; +import java.awt.Toolkit; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.geom.Arc2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ColorModel; +import java.awt.image.CropImageFilter; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferInt; +import java.awt.image.DirectColorModel; +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageObserver; +import java.awt.image.ImagingOpException; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; +import java.awt.image.SampleModel; +import java.awt.image.WritableRaster; +import java.awt.image.renderable.RenderContext; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +public class GdkGraphics2D extends Graphics2D +{ + ////////////////////////////////////// + ////// State Management Methods ////// + ////////////////////////////////////// + + static + { + if (! Configuration.GTK_CAIRO_ENABLED) + throw new Error("Grahics2D not implemented. " + + "Cairo was not found or disabled at configure time"); + + if (Configuration.INIT_LOAD_LIBRARY) + System.loadLibrary("gtkpeer"); + + if (GtkToolkit.useGraphics2D()) + initStaticState(); + } + + static native void initStaticState(); + + private final int native_state = GtkGenericPeer.getUniqueInteger(); + + // These are package-private to avoid accessor methods. + Paint paint; + Stroke stroke; + Color fg; + Color bg; + Shape clip; + AffineTransform transform; + private GtkComponentPeer component; + // This is package-private to avoid an accessor method. + Font font; + private RenderingHints hints; + private BufferedImage bimage; + private boolean pixelConversionRequired; + private int[] pixelBuffer; + // This is package-private to avoid an accessor method. + Composite comp; + private Stack stateStack; + + private native void initState(GtkComponentPeer component); + private native void initState(int width, int height); + private native void initState(int[] pixes, int width, int height); + private native void copyState(GdkGraphics2D g); + public native void dispose(); + private native void cairoSurfaceSetFilter(int filter); + native void connectSignals(GtkComponentPeer component); + + public void finalize() + { + dispose(); + } + + public Graphics create() + { + return new GdkGraphics2D(this); + } + + public Graphics create(int x, int y, int width, int height) + { + return new GdkGraphics2D(width, height); + } + + GdkGraphics2D(GdkGraphics2D g) + { + paint = g.paint; + stroke = g.stroke; + setRenderingHints(g.hints); + + if (g.fg.getAlpha() != -1) + fg = new Color(g.fg.getRed(), g.fg.getGreen(), g.fg.getBlue(), + g.fg.getAlpha()); + else + fg = new Color(g.fg.getRGB()); + + if (g.bg.getAlpha() != -1) + bg = new Color(g.bg.getRed(), g.bg.getGreen(), g.bg.getBlue(), + g.bg.getAlpha()); + else + bg = new Color(g.bg.getRGB()); + + if (g.clip == null) + clip = null; + else + clip = new Rectangle(g.getClipBounds()); + + if (g.transform == null) + transform = new AffineTransform(); + else + transform = new AffineTransform(g.transform); + + font = g.font; + component = g.component; + copyState(g); + + setColor(fg); + setBackground(bg); + setPaint(paint); + setStroke(stroke); + setTransform(transform); + setClip(clip); + stateStack = new Stack(); + } + + GdkGraphics2D(int width, int height) + { + initState(width, height); + + setColor(Color.black); + setBackground(new Color(0, 0, 0, 0)); + setPaint(getColor()); + setFont(new Font("SansSerif", Font.PLAIN, 12)); + setTransform(new AffineTransform()); + setStroke(new BasicStroke()); + setRenderingHints(getDefaultHints()); + + stateStack = new Stack(); + } + + GdkGraphics2D(GtkComponentPeer component) + { + this.component = component; + + if (component.isRealized()) + initComponentGraphics2D(); + else + connectSignals(component); + } + + void initComponentGraphics2D() + { + initState(component); + + setColor(component.awtComponent.getForeground()); + setBackground(component.awtComponent.getBackground()); + setPaint(getColor()); + setTransform(new AffineTransform()); + setStroke(new BasicStroke()); + setRenderingHints(getDefaultHints()); + setFont(new Font("SansSerif", Font.PLAIN, 12)); + + stateStack = new Stack(); + } + + GdkGraphics2D(BufferedImage bimage) + { + this.bimage = bimage; + this.pixelBuffer = findSimpleIntegerArray(bimage.getColorModel(), + bimage.getRaster()); + if (this.pixelBuffer == null) + { + this.pixelBuffer = new int[bimage.getRaster().getWidth() * bimage.getRaster() + .getHeight()]; + this.pixelConversionRequired = true; + } + else + { + this.pixelConversionRequired = false; + } + + initState(this.pixelBuffer, bimage.getWidth(), bimage.getHeight()); + + setColor(Color.black); + setBackground(new Color(0, 0, 0, 0)); + setPaint(getColor()); + setFont(new Font("SansSerif", Font.PLAIN, 12)); + setTransform(new AffineTransform()); + setStroke(new BasicStroke()); + setRenderingHints(getDefaultHints()); + + stateStack = new Stack(); + + // draw current buffered image to the pixmap associated + // with it, if the image is not equal to our paint buffer. + if (pixelConversionRequired) + drawImage(bimage, new AffineTransform(1, 0, 0, 1, 0, 0), bg, null); + } + + //////////////////////////////////// + ////// Native Drawing Methods ////// + //////////////////////////////////// + + // GDK drawing methods + private native void gdkDrawDrawable(GdkGraphics2D other, int x, int y); + + // drawing utility methods + private native void drawPixels(int[] pixels, int w, int h, int stride, + double[] i2u); + private native void setTexturePixels(int[] pixels, int w, int h, int stride); + private native void setGradient(double x1, double y1, double x2, double y2, + int r1, int g1, int b1, int a1, int r2, + int g2, int b2, int a2, boolean cyclic); + + // simple passthroughs to cairo + private native void cairoSave(); + private native void cairoRestore(); + private native void cairoSetMatrix(double[] m); + private native void cairoSetOperator(int cairoOperator); + private native void cairoSetRGBAColor(double red, double green, + double blue, double alpha); + private native void cairoSetFillRule(int cairoFillRule); + private native void cairoSetLineWidth(double width); + private native void cairoSetLineCap(int cairoLineCap); + private native void cairoSetLineJoin(int cairoLineJoin); + private native void cairoSetDash(double[] dashes, int ndash, double offset); + + private native void cairoSetMiterLimit(double limit); + private native void cairoNewPath(); + private native void cairoMoveTo(double x, double y); + private native void cairoLineTo(double x, double y); + private native void cairoCurveTo(double x1, double y1, double x2, double y2, + double x3, double y3); + private native void cairoRelMoveTo(double dx, double dy); + private native void cairoRelLineTo(double dx, double dy); + private native void cairoRelCurveTo(double dx1, double dy1, double dx2, + double dy2, double dx3, double dy3); + private native void cairoRectangle(double x, double y, double width, + double height); + private native void cairoClosePath(); + private native void cairoStroke(); + private native void cairoFill(); + private native void cairoClip(); + + ///////////////////////////////////////////// + ////// General Drawing Support Methods ////// + ///////////////////////////////////////////// + + private class DrawState + { + private Paint paint; + private Stroke stroke; + private Color fg; + private Color bg; + private Shape clip; + private AffineTransform transform; + private Font font; + private Composite comp; + + DrawState(GdkGraphics2D g) + { + this.paint = g.paint; + this.stroke = g.stroke; + this.fg = g.fg; + this.bg = g.bg; + this.clip = g.clip; + if (g.transform != null) + this.transform = (AffineTransform) g.transform.clone(); + this.font = g.font; + this.comp = g.comp; + } + + public void restore(GdkGraphics2D g) + { + g.paint = this.paint; + g.stroke = this.stroke; + g.fg = this.fg; + g.bg = this.bg; + g.clip = this.clip; + g.transform = this.transform; + g.font = this.font; + g.comp = this.comp; + } + } + + private void stateSave() + { + stateStack.push(new DrawState(this)); + cairoSave(); + } + + private void stateRestore() + { + ((DrawState) (stateStack.pop())).restore(this); + cairoRestore(); + } + + // Some operations (drawing rather than filling) require that their + // coords be shifted to land on 0.5-pixel boundaries, in order to land on + // "middle of pixel" coordinates and light up complete pixels. + private boolean shiftDrawCalls = false; + + private double shifted(double coord, boolean doShift) + { + if (doShift) + return Math.floor(coord) + 0.5; + else + return coord; + } + + private void walkPath(PathIterator p, boolean doShift) + { + double x = 0; + double y = 0; + double[] coords = new double[6]; + + cairoSetFillRule(p.getWindingRule()); + for (; ! p.isDone(); p.next()) + { + int seg = p.currentSegment(coords); + switch (seg) + { + case PathIterator.SEG_MOVETO: + x = shifted(coords[0], doShift); + y = shifted(coords[1], doShift); + cairoMoveTo(x, y); + break; + case PathIterator.SEG_LINETO: + x = shifted(coords[0], doShift); + y = shifted(coords[1], doShift); + cairoLineTo(x, y); + break; + case PathIterator.SEG_QUADTO: + // splitting a quadratic bezier into a cubic: + // see: http://pfaedit.sourceforge.net/bezier.html + double x1 = x + (2.0 / 3.0) * (shifted(coords[0], doShift) - x); + double y1 = y + (2.0 / 3.0) * (shifted(coords[1], doShift) - y); + + double x2 = x1 + (1.0 / 3.0) * (shifted(coords[2], doShift) - x); + double y2 = y1 + (1.0 / 3.0) * (shifted(coords[3], doShift) - y); + + x = shifted(coords[2], doShift); + y = shifted(coords[3], doShift); + cairoCurveTo(x1, y1, x2, y2, x, y); + break; + case PathIterator.SEG_CUBICTO: + x = shifted(coords[4], doShift); + y = shifted(coords[5], doShift); + cairoCurveTo(shifted(coords[0], doShift), + shifted(coords[1], doShift), + shifted(coords[2], doShift), + shifted(coords[3], doShift), x, y); + break; + case PathIterator.SEG_CLOSE: + cairoClosePath(); + break; + } + } + } + + private Map getDefaultHints() + { + HashMap defaultHints = new HashMap(); + + defaultHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); + + defaultHints.put(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_DEFAULT); + + defaultHints.put(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + + defaultHints.put(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + + defaultHints.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_DEFAULT); + + return defaultHints; + } + + public static int[] findSimpleIntegerArray (ColorModel cm, Raster raster) + { + if (cm == null || raster == null) + return null; + + if (! cm.getColorSpace().isCS_sRGB()) + return null; + + if (! (cm instanceof DirectColorModel)) + return null; + + DirectColorModel dcm = (DirectColorModel) cm; + + if (dcm.getRedMask() != 0x00FF0000 || dcm.getGreenMask() != 0x0000FF00 + || dcm.getBlueMask() != 0x000000FF) + return null; + + if (! (raster instanceof WritableRaster)) + return null; + + if (raster.getSampleModel().getDataType() != DataBuffer.TYPE_INT) + return null; + + if (! (raster.getDataBuffer() instanceof DataBufferInt)) + return null; + + DataBufferInt db = (DataBufferInt) raster.getDataBuffer(); + + if (db.getNumBanks() != 1) + return null; + + // Finally, we have determined that this is a single bank, [A]RGB-int + // buffer in sRGB space. It's worth checking all this, because it means + // that cairo can paint directly into the data buffer, which is very + // fast compared to all the normal copying and converting. + + return db.getData(); + } + + private void updateBufferedImage() + { + if (bimage != null && pixelConversionRequired) + { + int height = bimage.getHeight(); + int width = bimage.getWidth(); + int index = 0; + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) + bimage.setRGB(x, y, pixelBuffer[index++]); + } + } + + private boolean drawImage(Image img, AffineTransform xform, + Color bgcolor, ImageObserver obs) + { + if (img == null) + return false; + + // FIXME: I'll fix this, /Sven +// if (img instanceof GtkOffScreenImage +// && img.getGraphics() instanceof GdkGraphics2D +// && (xform == null || xform.getType() == AffineTransform.TYPE_IDENTITY +// || xform.getType() == AffineTransform.TYPE_TRANSLATION)) +// { +// // we are being asked to flush a double buffer from Gdk +// GdkGraphics2D g2 = (GdkGraphics2D) img.getGraphics(); +// gdkDrawDrawable(g2, (int) xform.getTranslateX(), +// (int) xform.getTranslateY()); + +// updateBufferedImage(); + +// return true; +// } +// else + { + // In this case, xform is an AffineTransform that transforms bounding + // box of the specified image from image space to user space. However + // when we pass this transform to cairo, cairo will use this transform + // to map "user coordinates" to "pixel" coordinates, which is the + // other way around. Therefore to get the "user -> pixel" transform + // that cairo wants from "image -> user" transform that we currently + // have, we will need to invert the transformation matrix. + AffineTransform invertedXform = new AffineTransform(); + + try + { + invertedXform = xform.createInverse(); + if (img instanceof BufferedImage) + { + // draw an image which has actually been loaded + // into memory fully + BufferedImage b = (BufferedImage) img; + return drawRaster(b.getColorModel(), b.getTile(0, 0), + invertedXform, bgcolor); + } + else + return this.drawImage(GdkPixbufDecoder.createBufferedImage(img + .getSource()), + xform, bgcolor, obs); + } + catch (NoninvertibleTransformException e) + { + throw new ImagingOpException("Unable to invert transform " + + xform.toString()); + } + } + } + + ////////////////////////////////////////////////// + ////// Implementation of Graphics2D Methods ////// + ////////////////////////////////////////////////// + + public void draw(Shape s) + { + if (stroke != null && ! (stroke instanceof BasicStroke)) + { + fill(stroke.createStrokedShape(s)); + return; + } + + cairoNewPath(); + + if (s instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) s; + cairoRectangle(shifted(r.getX(), shiftDrawCalls), + shifted(r.getY(), shiftDrawCalls), r.getWidth(), + r.getHeight()); + } + else + walkPath(s.getPathIterator(null), shiftDrawCalls); + cairoStroke(); + + updateBufferedImage(); + } + + public void fill(Shape s) + { + cairoNewPath(); + if (s instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) s; + cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + else + walkPath(s.getPathIterator(null), false); + + cairoFill(); + + updateBufferedImage(); + } + + public void clip(Shape s) + { + // update it + if (clip == null || s == null) + clip = s; + else if (s instanceof Rectangle2D && clip instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) s; + Rectangle2D curr = (Rectangle2D) clip; + clip = curr.createIntersection(r); + } + else + throw new UnsupportedOperationException(); + + // draw it + if (clip != null) + { + cairoNewPath(); + if (clip instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) clip; + cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + else + walkPath(clip.getPathIterator(null), false); + + // cairoClosePath (); + cairoClip(); + } + } + + public Paint getPaint() + { + return paint; + } + + public AffineTransform getTransform() + { + return (AffineTransform) transform.clone(); + } + + public void setPaint(Paint p) + { + if (paint == null) + return; + + paint = p; + if (paint instanceof Color) + { + setColor((Color) paint); + } + else if (paint instanceof TexturePaint) + { + TexturePaint tp = (TexturePaint) paint; + BufferedImage img = tp.getImage(); + + // map the image to the anchor rectangle + int width = (int) tp.getAnchorRect().getWidth(); + int height = (int) tp.getAnchorRect().getHeight(); + + double scaleX = width / (double) img.getWidth(); + double scaleY = width / (double) img.getHeight(); + + AffineTransform at = new AffineTransform(scaleX, 0, 0, scaleY, 0, 0); + AffineTransformOp op = new AffineTransformOp(at, getRenderingHints()); + BufferedImage texture = op.filter(img, null); + int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width); + setTexturePixels(pixels, width, height, width); + } + else if (paint instanceof GradientPaint) + { + GradientPaint gp = (GradientPaint) paint; + Point2D p1 = gp.getPoint1(); + Point2D p2 = gp.getPoint2(); + Color c1 = gp.getColor1(); + Color c2 = gp.getColor2(); + setGradient(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c1.getRed(), + c1.getGreen(), c1.getBlue(), c1.getAlpha(), c2.getRed(), + c2.getGreen(), c2.getBlue(), c2.getAlpha(), gp.isCyclic()); + } + else + throw new java.lang.UnsupportedOperationException(); + } + + public void setTransform(AffineTransform tx) + { + transform = tx; + if (transform != null) + { + double[] m = new double[6]; + transform.getMatrix(m); + cairoSetMatrix(m); + } + } + + public void transform(AffineTransform tx) + { + if (transform == null) + transform = new AffineTransform(tx); + else + transform.concatenate(tx); + setTransform(transform); + if (clip != null) + { + // FIXME: this should actuall try to transform the shape + // rather than degrade to bounds. + Rectangle2D r = clip.getBounds2D(); + double[] coords = new double[] + { + r.getX(), r.getY(), r.getX() + r.getWidth(), + r.getY() + r.getHeight() + }; + try + { + tx.createInverse().transform(coords, 0, coords, 0, 2); + r.setRect(coords[0], coords[1], coords[2] - coords[0], + coords[3] - coords[1]); + clip = r; + } + catch (java.awt.geom.NoninvertibleTransformException e) + { + } + } + } + + public void rotate(double theta) + { + transform(AffineTransform.getRotateInstance(theta)); + } + + public void rotate(double theta, double x, double y) + { + transform(AffineTransform.getRotateInstance(theta, x, y)); + } + + public void scale(double sx, double sy) + { + transform(AffineTransform.getScaleInstance(sx, sy)); + } + + public void translate(double tx, double ty) + { + transform(AffineTransform.getTranslateInstance(tx, ty)); + } + + public void translate(int x, int y) + { + translate((double) x, (double) y); + } + + public void shear(double shearX, double shearY) + { + transform(AffineTransform.getShearInstance(shearX, shearY)); + } + + public Stroke getStroke() + { + return stroke; + } + + public void setStroke(Stroke st) + { + stroke = st; + if (stroke instanceof BasicStroke) + { + BasicStroke bs = (BasicStroke) stroke; + cairoSetLineCap(bs.getEndCap()); + cairoSetLineWidth(bs.getLineWidth()); + cairoSetLineJoin(bs.getLineJoin()); + cairoSetMiterLimit(bs.getMiterLimit()); + float[] dashes = bs.getDashArray(); + if (dashes != null) + { + double[] double_dashes = new double[dashes.length]; + for (int i = 0; i < dashes.length; i++) + double_dashes[i] = dashes[i]; + cairoSetDash(double_dashes, double_dashes.length, + (double) bs.getDashPhase()); + } + } + } + + //////////////////////////////////////////////// + ////// Implementation of Graphics Methods ////// + //////////////////////////////////////////////// + + public void setPaintMode() + { + setComposite(java.awt.AlphaComposite.SrcOver); + } + + public void setXORMode(Color c) + { + setComposite(new gnu.java.awt.BitwiseXORComposite(c)); + } + + public void setColor(Color c) + { + if (c == null) + c = Color.BLACK; + + fg = c; + paint = c; + cairoSetRGBAColor(fg.getRed() / 255.0, fg.getGreen() / 255.0, + fg.getBlue() / 255.0, fg.getAlpha() / 255.0); + } + + public Color getColor() + { + return fg; + } + + public void clipRect(int x, int y, int width, int height) + { + clip(new Rectangle(x, y, width, height)); + } + + public Shape getClip() + { + return clip.getBounds2D(); //getClipInDevSpace(); + } + + public Rectangle getClipBounds() + { + if (clip == null) + return null; + else + return clip.getBounds(); + } + + protected Rectangle2D getClipInDevSpace() + { + Rectangle2D uclip = clip.getBounds2D(); + if (transform == null) + return uclip; + else + { + Point2D pos = transform.transform(new Point2D.Double(uclip.getX(), + uclip.getY()), + (Point2D) null); + Point2D extent = transform.deltaTransform(new Point2D.Double(uclip + .getWidth(), + uclip + .getHeight()), + (Point2D) null); + return new Rectangle2D.Double(pos.getX(), pos.getY(), extent.getX(), + extent.getY()); + } + } + + public void setClip(int x, int y, int width, int height) + { + setClip(new Rectangle2D.Double((double) x, (double) y, (double) width, + (double) height)); + } + + public void setClip(Shape s) + { + clip = s; + if (s != null) + { + cairoNewPath(); + if (s instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) s; + cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + else + walkPath(s.getPathIterator(null), false); + + // cairoClosePath (); + cairoClip(); + } + } + + private static BasicStroke draw3DRectStroke = new BasicStroke(); + + public void draw3DRect(int x, int y, int width, int height, boolean raised) + { + Stroke tmp = stroke; + setStroke(draw3DRectStroke); + super.draw3DRect(x, y, width, height, raised); + setStroke(tmp); + updateBufferedImage(); + } + + public void fill3DRect(int x, int y, int width, int height, boolean raised) + { + Stroke tmp = stroke; + setStroke(draw3DRectStroke); + super.fill3DRect(x, y, width, height, raised); + setStroke(tmp); + updateBufferedImage(); + } + + public void drawRect(int x, int y, int width, int height) + { + draw(new Rectangle(x, y, width, height)); + } + + public void fillRect(int x, int y, int width, int height) + { + cairoNewPath(); + cairoRectangle(x, y, width, height); + cairoFill(); + } + + public void clearRect(int x, int y, int width, int height) + { + cairoSetRGBAColor(bg.getRed() / 255.0, bg.getGreen() / 255.0, + bg.getBlue() / 255.0, 1.0); + cairoNewPath(); + cairoRectangle(x, y, width, height); + cairoFill(); + setColor(fg); + + updateBufferedImage(); + } + + public void setBackground(Color c) + { + bg = c; + } + + public Color getBackground() + { + return bg; + } + + private void doPolygon(int[] xPoints, int[] yPoints, int nPoints, + boolean close, boolean fill) + { + if (nPoints < 1) + return; + GeneralPath gp = new GeneralPath(PathIterator.WIND_EVEN_ODD); + gp.moveTo((float) xPoints[0], (float) yPoints[0]); + for (int i = 1; i < nPoints; i++) + gp.lineTo((float) xPoints[i], (float) yPoints[i]); + + if (close) + gp.closePath(); + + Shape sh = gp; + if (fill == false && stroke != null && ! (stroke instanceof BasicStroke)) + { + sh = stroke.createStrokedShape(gp); + fill = true; + } + + if (fill) + fill(sh); + else + draw(sh); + } + + public void drawLine(int x1, int y1, int x2, int y2) + { + int[] xp = new int[2]; + int[] yp = new int[2]; + + xp[0] = x1; + xp[1] = x2; + yp[0] = y1; + yp[1] = y2; + + doPolygon(xp, yp, 2, false, false); + } + + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) + { + doPolygon(xPoints, yPoints, nPoints, true, true); + } + + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) + { + doPolygon(xPoints, yPoints, nPoints, true, false); + } + + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) + { + doPolygon(xPoints, yPoints, nPoints, false, false); + } + + private boolean drawRaster(ColorModel cm, Raster r, + AffineTransform imageToUser, Color bgcolor) + { + if (r == null) + return false; + + SampleModel sm = r.getSampleModel(); + DataBuffer db = r.getDataBuffer(); + + if (db == null || sm == null) + return false; + + if (cm == null) + cm = ColorModel.getRGBdefault(); + + double[] i2u = new double[6]; + if (imageToUser != null) + imageToUser.getMatrix(i2u); + else + { + i2u[0] = 1; + i2u[1] = 0; + i2u[2] = 0; + i2u[3] = 1; + i2u[4] = 0; + i2u[5] = 0; + } + + int[] pixels = findSimpleIntegerArray(cm, r); + + if (pixels == null) + { + // FIXME: I don't think this code will work correctly with a non-RGB + // MultiPixelPackedSampleModel. Although this entire method should + // probably be rewritten to better utilize Cairo's different supported + // data formats. + if (sm instanceof MultiPixelPackedSampleModel) + { + pixels = r.getPixels(0, 0, r.getWidth(), r.getHeight(), pixels); + for (int i = 0; i < pixels.length; i++) + pixels[i] = cm.getRGB(pixels[i]); + } + else + { + pixels = new int[r.getWidth() * r.getHeight()]; + for (int i = 0; i < pixels.length; i++) + pixels[i] = cm.getRGB(db.getElem(i)); + } + } + + // Change all transparent pixels in the image to the specified bgcolor, + // or (if there's no alpha) fill in an alpha channel so that it paints + // correctly. + if (cm.hasAlpha()) + { + if (bgcolor != null && cm.hasAlpha()) + for (int i = 0; i < pixels.length; i++) + { + if (cm.getAlpha(pixels[i]) == 0) + pixels[i] = bgcolor.getRGB(); + } + } + else + for (int i = 0; i < pixels.length; i++) + pixels[i] |= 0xFF000000; + + drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u); + + updateBufferedImage(); + + return true; + } + + public void drawRenderedImage(RenderedImage image, AffineTransform xform) + { + drawRaster(image.getColorModel(), image.getData(), xform, bg); + } + + public void drawRenderableImage(RenderableImage image, AffineTransform xform) + { + drawRenderedImage(image.createRendering(new RenderContext(xform)), xform); + } + + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) + { + return drawImage(img, xform, bg, obs); + } + + public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y) + { + Image filtered = op.filter(image, null); + drawImage(filtered, new AffineTransform(1f, 0f, 0f, 1f, x, y), bg, null); + } + + public boolean drawImage(Image img, int x, int y, ImageObserver observer) + { + return drawImage(img, new AffineTransform(1f, 0f, 0f, 1f, x, y), bg, + observer); + } + + /////////////////////////////////////////////// + ////// Unimplemented Stubs and Overloads ////// + /////////////////////////////////////////////// + + public boolean hit(Rectangle rect, Shape text, boolean onStroke) + { + throw new java.lang.UnsupportedOperationException(); + } + + public GraphicsConfiguration getDeviceConfiguration() + { + throw new java.lang.UnsupportedOperationException(); + } + + public void setComposite(Composite comp) + { + this.comp = comp; + + if (comp instanceof AlphaComposite) + { + AlphaComposite a = (AlphaComposite) comp; + cairoSetOperator(a.getRule()); + Color c = getColor(); + setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), + (int) (a.getAlpha() * ((float) c.getAlpha())))); + } + else + throw new java.lang.UnsupportedOperationException(); + } + + public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) + { + hints.put(hintKey, hintValue); + + if (hintKey.equals(RenderingHints.KEY_INTERPOLATION) + || hintKey.equals(RenderingHints.KEY_ALPHA_INTERPOLATION)) + { + if (hintValue.equals(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) + cairoSurfaceSetFilter(0); + + else if (hintValue.equals(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) + cairoSurfaceSetFilter(1); + + else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)) + cairoSurfaceSetFilter(2); + + else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)) + cairoSurfaceSetFilter(3); + + else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) + cairoSurfaceSetFilter(4); + } + + shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE) + || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); + } + + public Object getRenderingHint(RenderingHints.Key hintKey) + { + return hints.get(hintKey); + } + + public void setRenderingHints(Map hints) + { + this.hints = new RenderingHints(getDefaultHints()); + this.hints.add(new RenderingHints(hints)); + + if (hints.containsKey(RenderingHints.KEY_INTERPOLATION)) + { + if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) + cairoSurfaceSetFilter(0); + + else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) + cairoSurfaceSetFilter(1); + } + + if (hints.containsKey(RenderingHints.KEY_ALPHA_INTERPOLATION)) + { + if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)) + cairoSurfaceSetFilter(2); + + else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)) + cairoSurfaceSetFilter(3); + + else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) + cairoSurfaceSetFilter(4); + } + + shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE) + || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); + } + + public void addRenderingHints(Map hints) + { + this.hints.add(new RenderingHints(hints)); + } + + public RenderingHints getRenderingHints() + { + return hints; + } + + public Composite getComposite() + { + if (comp == null) + return AlphaComposite.SrcOver; + else + return comp; + } + + public FontRenderContext getFontRenderContext() + { + return new FontRenderContext(transform, true, true); + } + + public void copyArea(int x, int y, int width, int height, int dx, int dy) + { + throw new java.lang.UnsupportedOperationException(); + } + + public void drawArc(int x, int y, int width, int height, int startAngle, + int arcAngle) + { + draw(new Arc2D.Double((double) x, (double) y, (double) width, + (double) height, (double) startAngle, + (double) arcAngle, Arc2D.OPEN)); + } + + public boolean drawImage(Image img, int x, int y, Color bgcolor, + ImageObserver observer) + { + return drawImage(img, x, y, img.getWidth(observer), + img.getHeight(observer), bgcolor, observer); + } + + public boolean drawImage(Image img, int x, int y, int width, int height, + Color bgcolor, ImageObserver observer) + { + double scaleX = width / (double) img.getWidth(observer); + double scaleY = height / (double) img.getHeight(observer); + + return drawImage(img, new AffineTransform(scaleX, 0f, 0f, scaleY, x, y), + bgcolor, observer); + } + + public boolean drawImage(Image img, int x, int y, int width, int height, + ImageObserver observer) + { + return drawImage(img, x, y, width, height, bg, observer); + } + + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, Color bgcolor, + ImageObserver observer) + { + if (img == null) + return false; + + Image subImage; + + int sourceWidth = sx2 - sx1; + int sourceHeight = sy2 - sy1; + + int destWidth = dx2 - dx1; + int destHeight = dy2 - dy1; + + double scaleX = destWidth / (double) sourceWidth; + double scaleY = destHeight / (double) sourceHeight; + + // Get the subimage of the source enclosed in the + // rectangle specified by sx1, sy1, sx2, sy2 + + if (img instanceof BufferedImage) + { + BufferedImage b = (BufferedImage) img; + subImage = b.getSubimage(sx1, sy1, sx2, sy2); + } + else + { + // FIXME: This code currently doesn't work. Null Pointer + // exception is thrown in this case. This happens + // because img.getSource() always returns null, since source gets + // never initialized when it is created with the help of + // createImage(int width, int height). + CropImageFilter filter = new CropImageFilter(sx1, sx2, sx2, sy2); + FilteredImageSource src = new FilteredImageSource(img.getSource(), + filter); + + subImage = Toolkit.getDefaultToolkit().createImage(src); + } + + return drawImage(subImage, + new AffineTransform(scaleX, 0, 0, scaleY, dx1, dy1), + bgcolor, observer); + } + + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + ImageObserver observer) + { + return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bg, observer); + } + + public void drawOval(int x, int y, int width, int height) + { + drawArc(x, y, width, height, 0, 360); + } + + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, + int arcHeight) + { + if (arcWidth > width) + arcWidth = width; + if (arcHeight > height) + arcHeight = height; + + int xx = x + width - arcWidth; + int yy = y + height - arcHeight; + + drawArc(x, y, arcWidth, arcHeight, 90, 90); + drawArc(xx, y, arcWidth, arcHeight, 0, 90); + drawArc(xx, yy, arcWidth, arcHeight, 270, 90); + drawArc(x, yy, arcWidth, arcHeight, 180, 90); + + int y1 = y + arcHeight / 2; + int y2 = y + height - arcHeight / 2; + drawLine(x, y1, x, y2); + drawLine(x + width, y1, x + width, y2); + + int x1 = x + arcWidth / 2; + int x2 = x + width - arcWidth / 2; + drawLine(x1, y, x2, y); + drawLine(x1, y + height, x2, y + height); + } + + // these are the most accelerated painting paths + native void cairoDrawGlyphVector(GdkFontPeer font, + float x, float y, int n, + int[] codes, float[] positions); + + native void cairoDrawGdkTextLayout(GdkTextLayout gl, + float x, float y); + + GdkFontPeer getFontPeer() + { + return (GdkFontPeer) getFont().getPeer(); + } + + public void drawGdkTextLayout(GdkTextLayout gl, float x, float y) + { + cairoDrawGdkTextLayout (gl, x, y); + updateBufferedImage (); + } + + public void drawString(String str, float x, float y) + { + drawGlyphVector(getFont().createGlyphVector(null, str), x, y); + updateBufferedImage (); + } + + public void drawString(String str, int x, int y) + { + drawString (str, (float) x, (float) y); + } + + public void drawString(AttributedCharacterIterator ci, int x, int y) + { + drawString (ci, (float) x, (float) y); + } + + public void drawGlyphVector(GlyphVector gv, float x, float y) + { + int n = gv.getNumGlyphs (); + int[] codes = gv.getGlyphCodes (0, n, null); + float[] positions = gv.getGlyphPositions (0, n, null); + + setFont (gv.getFont ()); + cairoDrawGlyphVector (getFontPeer(), x, y, n, codes, positions); + updateBufferedImage (); + } + + public void drawString(AttributedCharacterIterator ci, float x, float y) + { + GlyphVector gv = getFont().createGlyphVector(getFontRenderContext(), ci); + drawGlyphVector(gv, x, y); + } + + public void fillArc(int x, int y, int width, int height, int startAngle, + int arcAngle) + { + fill(new Arc2D.Double((double) x, (double) y, (double) width, + (double) height, (double) startAngle, + (double) arcAngle, Arc2D.OPEN)); + } + + public void fillOval(int x, int y, int width, int height) + { + fillArc(x, y, width, height, 0, 360); + } + + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, + int arcHeight) + { + if (arcWidth > width) + arcWidth = width; + if (arcHeight > height) + arcHeight = height; + + int xx = x + width - arcWidth; + int yy = y + height - arcHeight; + + fillArc(x, y, arcWidth, arcHeight, 90, 90); + fillArc(xx, y, arcWidth, arcHeight, 0, 90); + fillArc(xx, yy, arcWidth, arcHeight, 270, 90); + fillArc(x, yy, arcWidth, arcHeight, 180, 90); + + fillRect(x, y + arcHeight / 2, width, height - arcHeight + 1); + fillRect(x + arcWidth / 2, y, width - arcWidth + 1, height); + } + + public Font getFont() + { + if (font == null) + return new Font("SansSerif", Font.PLAIN, 12); + return font; + } + + // Until such time as pango is happy to talk directly to cairo, we + // actually need to redirect some calls from the GtkFontPeer and + // GtkFontMetrics into the drawing kit and ask cairo ourselves. + + static native void releasePeerGraphicsResource(GdkFontPeer f); + + public FontMetrics getFontMetrics() + { + return getFontMetrics(getFont()); + } + + public FontMetrics getFontMetrics(Font f) + { + // the reason we go via the toolkit here is to try to get + // a cached object. the toolkit keeps such a cache. + return Toolkit.getDefaultToolkit().getFontMetrics(f); + } + + public void setFont(Font f) + { + if (f.getPeer() instanceof GdkFontPeer) + font = f; + else + font = + ((ClasspathToolkit)(Toolkit.getDefaultToolkit())) + .getFont(f.getName(), f.getAttributes()); + } + + public String toString() + { + return (getClass().getName() + + "[font=" + getFont().toString() + + ",color=" + fg.toString() + + "]"); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java new file mode 100644 index 0000000..bfad87a --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java @@ -0,0 +1,138 @@ +/* GdkGraphicsConfiguration.java -- describes characteristics of graphics + Copyright (C) 2000, 2001, 2002, 2003, 2004 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 gnu.java.awt.peer.gtk; + +import java.awt.BufferCapabilities; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.ImageCapabilities; +import java.awt.Rectangle; + +import java.awt.geom.AffineTransform; + +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.VolatileImage; + +public class GdkGraphicsConfiguration + extends GraphicsConfiguration +{ + GdkScreenGraphicsDevice gdkScreenGraphicsDevice; + ColorModel cm; + Rectangle bounds; + + public GtkToolkit getToolkit() + { + return gdkScreenGraphicsDevice.getToolkit(); + } + + public GdkGraphicsConfiguration(GdkScreenGraphicsDevice dev) + { + this.gdkScreenGraphicsDevice = dev; + cm = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).getColorModel(); + bounds = getToolkit().getBounds(); + } + + public GraphicsDevice getDevice() + { + return gdkScreenGraphicsDevice; + } + + public BufferedImage createCompatibleImage(int w, int h) + { + return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + } + + public BufferedImage createCompatibleImage(int w, int h, + int transparency) + { + return createCompatibleImage(w, h); + } + + public VolatileImage createCompatibleVolatileImage(int w, int h) + { + return new GtkVolatileImage(w, h); + } + + public VolatileImage createCompatibleVolatileImage(int w, int h, + ImageCapabilities caps) + throws java.awt.AWTException + { + return new GtkVolatileImage(w, h, caps); + } + + public ColorModel getColorModel() + { + return cm; + } + + public ColorModel getColorModel(int transparency) + { + return getColorModel(); + } + + public AffineTransform getDefaultTransform() + { + // FIXME: extract the GDK DPI information here. + return new AffineTransform(); + } + + public AffineTransform getNormalizingTransform() + { + // FIXME: extract the GDK DPI information here. + return new AffineTransform(); + } + + public Rectangle getBounds() + { + return bounds; + } + + public BufferCapabilities getBufferCapabilities() + { + return new BufferCapabilities(getImageCapabilities(), + getImageCapabilities(), + BufferCapabilities.FlipContents.UNDEFINED); + } + + public ImageCapabilities getImageCapabilities() + { + return new ImageCapabilities(false); + } + +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java new file mode 100644 index 0000000..4f9d1c2 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java @@ -0,0 +1,107 @@ +/* GdkGraphicsEnvironment.java -- information about the graphics environment + Copyright (C) 2004, 2005 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.Font; +import java.awt.Graphics2D; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.HeadlessException; +import java.awt.image.BufferedImage; +import java.util.Locale; + +public class GdkGraphicsEnvironment extends GraphicsEnvironment +{ + GtkToolkit gtkToolkit; + + public GtkToolkit getToolkit() + { + return gtkToolkit; + } + + public GdkGraphicsEnvironment (GtkToolkit tk) + { + super(); + gtkToolkit = tk; + } + + public GraphicsDevice[] getScreenDevices () + { + // FIXME: Support multiple screens, since GDK can. + return new GraphicsDevice[] { new GdkScreenGraphicsDevice (this) }; + } + + public GraphicsDevice getDefaultScreenDevice () + { + if (GraphicsEnvironment.isHeadless ()) + throw new HeadlessException (); + + return new GdkScreenGraphicsDevice (this); + } + + public Graphics2D createGraphics (BufferedImage image) + { + return new GdkGraphics2D (image); + } + + private native int nativeGetNumFontFamilies(); + private native void nativeGetFontFamilies(String[] family_names); + + public Font[] getAllFonts () + { + throw new java.lang.UnsupportedOperationException (); + } + + public String[] getAvailableFontFamilyNames () + { + String[] family_names; + int array_size; + + array_size = nativeGetNumFontFamilies(); + family_names = new String[array_size]; + + nativeGetFontFamilies(family_names); + return family_names; + } + + public String[] getAvailableFontFamilyNames (Locale l) + { + throw new java.lang.UnsupportedOperationException (); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java new file mode 100644 index 0000000..57d5a36 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -0,0 +1,681 @@ +/* GdkPixbufDecoder.java -- Image data decoding object + Copyright (C) 2003, 2004, 2005 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.classpath.Configuration; + +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageProducer; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; +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 + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("gtkpeer"); + } + initStaticState (); + } + + 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 + native void initState (); + native void pumpBytes (byte[] bytes, int len) throws IOException; + native void pumpDone () throws IOException; + native void finish (boolean needsClose); + static native void streamImage(int[] bytes, String format, int width, int height, boolean hasAlpha, DataOutput sink); + + // gdk-pixbuf provids data in RGBA format + static final ColorModel cm = new DirectColorModel (32, 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff); + 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 + 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 + 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; + initState(); + needsClose = true; + while ((len = is.read (bytes)) != -1) + pumpBytes (bytes, len); + 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() + { + 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) + throw new IllegalArgumentException("extension is 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 + { + 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 = GdkGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras); + + if (pixels == null) + { + BufferedImage img = new BufferedImage(width, height, + (model != null && model.hasAlpha() ? + BufferedImage.TYPE_INT_ARGB + : 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 = GdkGraphics2D.findSimpleIntegerArray (img.getColorModel(), + img.getRaster()); + model = img.getColorModel(); + } + + processImageStarted(1); + streamImage(pixels, this.ext, width, height, model.hasAlpha(), + (DataOutput) this.getOutput()); + processImageComplete(); + } + } + + 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) + { + bufferedImage = new BufferedImage (width, height, (model != null && model.hasAlpha() ? + BufferedImage.TYPE_INT_ARGB + : 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); + dec = new GdkPixbufDecoder((InputStream) getInput()); + } + + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException + { + return getBufferedImage (); + } + } + + // remaining helper class and static method is a convenience for the Gtk + // peers, for loading a BufferedImage in off a disk file without going + // through the whole imageio system. + + public static BufferedImage createBufferedImage (String filename) + { + GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(), + "png", // reader auto-detects, doesn't matter + new GdkPixbufDecoder (filename)); + return r.getBufferedImage (); + } + + public static BufferedImage createBufferedImage (URL u) + { + GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(), + "png", // reader auto-detects, doesn't matter + new GdkPixbufDecoder (u)); + return r.getBufferedImage (); + } + + public static BufferedImage createBufferedImage (byte[] imagedata, int imageoffset, + int imagelength) + { + GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(), + "png", // reader auto-detects, doesn't matter + new GdkPixbufDecoder (imagedata, + imageoffset, + imagelength)); + return r.getBufferedImage (); + } + + public static BufferedImage createBufferedImage (ImageProducer producer) + { + GdkPixbufReader r = new GdkPixbufReader (getReaderSpi(), "png" /* ignored */, null); + producer.startProduction(r); + return r.getBufferedImage (); + } + +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java new file mode 100644 index 0000000..6d0218d --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java @@ -0,0 +1,94 @@ +/* GdkRobot.java -- an XTest implementation of RobotPeer + Copyright (C) 2004, 2005 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.AWTException; +import java.awt.GraphicsDevice; +import java.awt.Rectangle; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.peer.RobotPeer; + +/** + * Implements the RobotPeer interface using the XTest extension. + * + * @author Thomas Fitzsimmons + */ +public class GdkRobotPeer implements RobotPeer +{ + // gdk-pixbuf provides data in RGBA format + static final ColorModel cm = new DirectColorModel (32, 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff); + + public GdkRobotPeer (GraphicsDevice screen) throws AWTException + { + // FIXME: make use of screen parameter when GraphicsDevice is + // implemented. + if (!initXTest ()) + throw new AWTException ("XTest extension not supported"); + } + + native boolean initXTest (); + + // RobotPeer methods + public native void mouseMove (int x, int y); + public native void mousePress (int buttons); + public native void mouseRelease (int buttons); + public native void mouseWheel (int wheelAmt); + public native void keyPress (int keycode); + public native void keyRelease (int keycode); + native int[] nativeGetRGBPixels (int x, int y, int width, int height); + + public int getRGBPixel (int x, int y) + { + return cm.getRGB (nativeGetRGBPixels (x, y, 1, 1)[0]); + } + + public int[] getRGBPixels (Rectangle r) + { + int[] gdk_pixels = nativeGetRGBPixels (r.x, r.y, r.width, r.height); + int[] pixels = new int[r.width * r.height]; + + for (int i = 0; i < r.width * r.height; i++) + pixels[i] = cm.getRGB (gdk_pixels[i]); + + return pixels; + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java new file mode 100644 index 0000000..2bf9d23 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java @@ -0,0 +1,115 @@ +/* GdkScreenGraphicsDevice.java -- information about a screen device + Copyright (C) 2004, 2005 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.Dimension; +import java.awt.DisplayMode; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; + +public class GdkScreenGraphicsDevice extends GraphicsDevice +{ + GdkGraphicsEnvironment env; + + public GtkToolkit getToolkit() + { + return env.getToolkit(); + } + + public GdkScreenGraphicsDevice (GdkGraphicsEnvironment e) + { + super (); + env = e; + } + + public int getType () + { + return GraphicsDevice.TYPE_RASTER_SCREEN; + } + + public String getIDstring () + { + // FIXME: query X for this string + return "default GDK device ID string"; + } + + public GraphicsConfiguration[] getConfigurations () + { + // FIXME: query X for the list of possible configurations + return new GraphicsConfiguration [] { new GdkGraphicsConfiguration(this) }; + } + + public GraphicsConfiguration getDefaultConfiguration () + { + + // FIXME: query X for default configuration + return new GdkGraphicsConfiguration(this); + } + + + /** + * Returns the current display mode of this device, or null if unknown. + * + * @return the current display mode + * @see #setDisplayMode(DisplayMode) + * @see #getDisplayModes() + * @since 1.4 + */ + public DisplayMode getDisplayMode() + { + // determine display mode + Dimension dim = getToolkit().getScreenSize(); + DisplayMode mode = new DisplayMode(dim.width, dim.height, 0, + DisplayMode.REFRESH_RATE_UNKNOWN); + return mode; + } + + /** + * This device does not yet support fullscreen exclusive mode, so this + * returns <code>false</code>. + * + * @return <code>false</code> + * @since 1.4 + */ + public boolean isFullScreenSupported() + { + return false; + } + +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java new file mode 100644 index 0000000..ff51745 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java @@ -0,0 +1,434 @@ +/* GdkTextLayout.java + Copyright (C) 2003, 2005 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.classpath.Configuration; +import gnu.java.awt.peer.ClasspathTextLayoutPeer; + +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +import java.awt.font.TextAttribute; +import java.awt.font.TextHitInfo; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.text.CharacterIterator; + +/** + * This is an implementation of the text layout peer interface which + * delegates all the hard work to pango. + * + * @author Graydon Hoare + */ + +public class GdkTextLayout + implements ClasspathTextLayoutPeer +{ + // native side, plumbing, etc. + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("gtkpeer"); + } + initStaticState (); + } + private native void setText(String str); + private native void getExtents(double[] inkExtents, + double[] logExtents); + private native void indexToPos(int idx, double[] pos); + private native void initState (); + private native void dispose (); + static native void initStaticState(); + private final int native_state = GtkGenericPeer.getUniqueInteger (); + protected void finalize () + { + dispose (); + } + + // we hold on to these to make sure we can render when presented + // with non-GdkGraphics2D paint targets + private AttributedString attributedString; + private FontRenderContext fontRenderContext; + + public GdkTextLayout(AttributedString str, FontRenderContext frc) + { + initState(); + attributedString = str; + fontRenderContext = frc; + } + + protected class CharacterIteratorProxy + implements CharacterIterator + { + public CharacterIterator target; + public int begin; + public int limit; + public int index; + + public CharacterIteratorProxy (CharacterIterator ci) + { + target = ci; + } + + public int getBeginIndex () + { + return begin; + } + + public int getEndIndex () + { + return limit; + } + + public int getIndex () + { + return index; + } + + public char setIndex (int idx) + throws IllegalArgumentException + { + if (idx < begin || idx >= limit) + throw new IllegalArgumentException (); + char ch = target.setIndex (idx); + index = idx; + return ch; + } + + public char first () + { + int save = target.getIndex (); + char ch = target.setIndex (begin); + target.setIndex (save); + return ch; + } + + public char last () + { + if (begin == limit) + return this.first (); + + int save = target.getIndex (); + char ch = target.setIndex (limit - 1); + target.setIndex (save); + return ch; + } + + public char current () + { + return target.current(); + } + + public char next () + { + if (index >= limit - 1) + return CharacterIterator.DONE; + else + { + index++; + return target.next(); + } + } + + public char previous () + { + if (index <= begin) + return CharacterIterator.DONE; + else + { + index--; + return target.previous (); + } + } + + public Object clone () + { + CharacterIteratorProxy cip = new CharacterIteratorProxy (this.target); + cip.begin = this.begin; + cip.limit = this.limit; + cip.index = this.index; + return cip; + } + + } + + + // public side + + public void draw (Graphics2D g2, float x, float y) + { + if (g2 instanceof GdkGraphics2D) + { + // we share pango structures directly with GdkGraphics2D + // when legal + GdkGraphics2D gg2 = (GdkGraphics2D) g2; + gg2.drawGdkTextLayout(this, x, y); + } + else + { + // falling back to a rather tedious layout algorithm when + // not legal + AttributedCharacterIterator ci = attributedString.getIterator (); + CharacterIteratorProxy proxy = new CharacterIteratorProxy (ci); + Font defFont = g2.getFont (); + + /* Note: this implementation currently only interprets FONT text + * attributes. There is a reasonable argument to be made for some + * attributes being interpreted out here, where we have control of the + * Graphics2D and can construct or derive new fonts, and some + * attributes being interpreted by the GlyphVector itself. So far, for + * all attributes except FONT we do neither. + */ + + for (char c = ci.first (); + c != CharacterIterator.DONE; + c = ci.next ()) + { + proxy.begin = ci.getIndex (); + proxy.limit = ci.getRunLimit(TextAttribute.FONT); + if (proxy.limit <= proxy.begin) + continue; + + proxy.index = proxy.begin; + + Object fnt = ci.getAttribute(TextAttribute.FONT); + GlyphVector gv; + if (fnt instanceof Font) + gv = ((Font)fnt).createGlyphVector (fontRenderContext, proxy); + else + gv = defFont.createGlyphVector (fontRenderContext, proxy); + + g2.drawGlyphVector (gv, x, y); + + int n = gv.getNumGlyphs (); + for (int i = 0; i < n; ++i) + { + GlyphMetrics gm = gv.getGlyphMetrics (i); + if (gm.getAdvanceX() == gm.getAdvance ()) + x += gm.getAdvanceX (); + else + y += gm.getAdvanceY (); + } + } + } + } + + public TextHitInfo getStrongCaret (TextHitInfo hit1, + TextHitInfo hit2) + { + throw new Error("not implemented"); + } + + public byte getBaseline () + { + throw new Error("not implemented"); + } + + public boolean isLeftToRight () + { + throw new Error("not implemented"); + } + + public boolean isVertical () + { + throw new Error("not implemented"); + } + + public float getAdvance () + { + throw new Error("not implemented"); + } + + public float getAscent () + { + throw new Error("not implemented"); + } + + public float getDescent () + { + throw new Error("not implemented"); + } + + public float getLeading () + { + throw new Error("not implemented"); + } + + public int getCharacterCount () + { + throw new Error("not implemented"); + } + + public byte getCharacterLevel (int index) + { + throw new Error("not implemented"); + } + + public float[] getBaselineOffsets () + { + throw new Error("not implemented"); + } + + public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint) + { + throw new Error("not implemented"); + } + + public Rectangle2D getBounds () + { + double[] inkExtents = new double[4]; + double[] logExtents = new double[4]; + getExtents(inkExtents, logExtents); + return new Rectangle2D.Double(logExtents[0], logExtents[1], + logExtents[2], logExtents[3]); + } + + public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds) + { + throw new Error("not implemented"); + } + + public Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds) + { + throw new Error("not implemented"); + } + + public Shape[] getCaretShapes (int offset, Rectangle2D bounds, + TextLayout.CaretPolicy policy) + { + throw new Error("not implemented"); + } + + public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint, + Rectangle2D bounds) + { + AffineTransform at = new AffineTransform(); + GeneralPath gp = new GeneralPath(); + double [] rect = new double[4]; + Rectangle2D tmp = new Rectangle2D.Double(); + for (int i = firstEndpoint; i <= secondEndpoint; ++i) + { + indexToPos(i, rect); + tmp.setRect(rect[0], rect[1], rect[2], rect[3]); + Rectangle2D.intersect(tmp, bounds, tmp); + gp.append(tmp.getPathIterator(at), false); + } + return gp; + } + + public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint, + TextHitInfo secondEndpoint) + { + throw new Error("not implemented"); + } + + public TextHitInfo getNextLeftHit (int offset, TextLayout.CaretPolicy policy) + { + throw new Error("not implemented"); + } + public TextHitInfo getNextRightHit (int offset, TextLayout.CaretPolicy policy) + { + throw new Error("not implemented"); + } + public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds) + { + throw new Error("not implemented"); + } + public TextHitInfo getVisualOtherHit (TextHitInfo hit) + { + throw new Error("not implemented"); + } + + public float getVisibleAdvance () + { + throw new Error("not implemented"); + } + + public Shape getOutline (AffineTransform tx) + { + throw new Error("not implemented"); + } + + public Shape getVisualHighlightShape (TextHitInfo firstEndpoint, + TextHitInfo secondEndpoint, + Rectangle2D bounds) + { + throw new Error("not implemented"); + } + + + public TextLayout getJustifiedLayout (float justificationWidth) + { + throw new Error("not implemented"); + } + + public void handleJustify (float justificationWidth) + { + throw new Error("not implemented"); + } + + public Object clone () + { + throw new Error("not implemented"); + } + + public int hashCode () + { + throw new Error("not implemented"); + } + + public boolean equals (ClasspathTextLayoutPeer tl) + { + throw new Error("not implemented"); + } + + public String toString () + { + throw new Error("not implemented"); + } + +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java new file mode 100644 index 0000000..ab5df9f --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java @@ -0,0 +1,107 @@ +/* GtkButtonPeer.java -- Implements ButtonPeer with GTK + Copyright (C) 1998, 1999, 2004 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.AWTEvent; +import java.awt.Button; +import java.awt.Component; +import java.awt.Point; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.peer.ButtonPeer; + +public class GtkButtonPeer extends GtkComponentPeer + implements ButtonPeer +{ + native void create (String label); + + public native void connectSignals (); + + native void gtkWidgetModifyFont (String name, int style, int size); + native void gtkSetLabel (String label); + native void gtkWidgetSetForeground (int red, int green, int blue); + native void gtkWidgetSetBackground (int red, int green, int blue); + native void gtkActivate (); + native void gtkWidgetRequestFocus (); + native void setNativeBounds (int x, int y, int width, int height); + + public GtkButtonPeer (Button b) + { + super (b); + } + + void create () + { + create (((Button) awtComponent).getLabel ()); + } + + public void setLabel (String label) + { + gtkSetLabel(label); + } + + public void handleEvent (AWTEvent e) + { + if (e.getID () == MouseEvent.MOUSE_RELEASED && isEnabled ()) + { + MouseEvent me = (MouseEvent) e; + Point p = me.getPoint(); + p.translate(((Component) me.getSource()).getX(), + ((Component) me.getSource()).getY()); + if (!me.isConsumed () + && (me.getModifiersEx () & MouseEvent.BUTTON1_DOWN_MASK) != 0 + && awtComponent.getBounds().contains(p)) + postActionEvent (((Button) awtComponent).getActionCommand (), + me.getModifiersEx ()); + } + + if (e.getID () == KeyEvent.KEY_PRESSED) + { + KeyEvent ke = (KeyEvent) e; + if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_SPACE) + { + postActionEvent (((Button) awtComponent).getActionCommand (), + ke.getModifiersEx ()); + gtkActivate (); + } + } + + super.handleEvent (e); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCanvasPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCanvasPeer.java new file mode 100644 index 0000000..dc21761 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCanvasPeer.java @@ -0,0 +1,100 @@ +/* GtkCanvasPeer.java + Copyright (C) 1998, 1999 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.AWTEvent; +import java.awt.Canvas; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.PaintEvent; +import java.awt.peer.CanvasPeer; + +public class GtkCanvasPeer extends GtkComponentPeer implements CanvasPeer +{ + native void create (); + + public GtkCanvasPeer (Canvas c) + { + super (c); + } + + public Graphics getGraphics () + { + if (GtkToolkit.useGraphics2D ()) + return new GdkGraphics2D (this); + else + return new GdkGraphics (this); + } + + public void handleEvent (AWTEvent event) + { + int id = event.getID(); + + switch (id) + { + case PaintEvent.PAINT: + case PaintEvent.UPDATE: + { + try + { + Graphics g = getGraphics (); + g.setClip (((PaintEvent)event).getUpdateRect()); + + if (id == PaintEvent.PAINT) + awtComponent.paint (g); + else + awtComponent.update (g); + + g.dispose (); + } + catch (InternalError e) + { + System.err.println (e); + } + } + break; + } + } + + /* Preferred size for a drawing widget is always what the user requested */ + public Dimension getPreferredSize () + { + return awtComponent.getSize (); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java new file mode 100644 index 0000000..46b0733 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java @@ -0,0 +1,86 @@ +/* GtkCheckboxGroupPeer.java - Wrap a CheckboxGroup + Copyright (C) 2002 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.CheckboxGroup; +import java.util.WeakHashMap; + +// Note that there is no peer interface for a CheckboxGroup. We +// introduce our own in order to make it easier to keep a piece of +// native state for each one. +public class GtkCheckboxGroupPeer extends GtkGenericPeer +{ + // This maps from a CheckboxGroup to the native peer. + private static WeakHashMap map = new WeakHashMap (); + + // Find the native peer corresponding to a CheckboxGroup. + public static synchronized GtkCheckboxGroupPeer + getCheckboxGroupPeer (CheckboxGroup group) + { + if (group == null) + return null; + GtkCheckboxGroupPeer nat = (GtkCheckboxGroupPeer) map.get (group); + if (nat == null) + { + nat = new GtkCheckboxGroupPeer (); + map.put (group, nat); + } + return nat; + } + + private GtkCheckboxGroupPeer () + { + // We don't need any special state here. Note that we can't store + // a reference to the java-side CheckboxGroup. That would mean + // they could never be collected. + super (null); + } + + // Dispose of our native resources. + public native void dispose (); + + // Remove a given checkbox from this group. + public native void remove (GtkCheckboxPeer box); + + // When collected, clean up the native state. + protected void finalize () + { + dispose (); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java new file mode 100644 index 0000000..01a6e31 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java @@ -0,0 +1,69 @@ +/* GtkCheckboxMenuItemPeer.java -- Implements CheckboxMenuItemPeer with GTK+ + Copyright (C) 1999, 2005 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.CheckboxMenuItem; +import java.awt.ItemSelectable; +import java.awt.event.ItemEvent; +import java.awt.peer.CheckboxMenuItemPeer; + +public class GtkCheckboxMenuItemPeer extends GtkMenuItemPeer + implements CheckboxMenuItemPeer +{ + native void create (String label); + + public GtkCheckboxMenuItemPeer (CheckboxMenuItem menu) + { + super (menu); + setState (menu.getState ()); + } + + public native void setState(boolean t); + + protected void postMenuActionEvent () + { + CheckboxMenuItem item = (CheckboxMenuItem)awtWidget; + q().postEvent (new ItemEvent ((ItemSelectable)awtWidget, + ItemEvent.ITEM_STATE_CHANGED, + item.getActionCommand(), + item.getState() ? ItemEvent.DESELECTED : ItemEvent.SELECTED)); + + super.postMenuActionEvent(); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java new file mode 100644 index 0000000..8517572 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java @@ -0,0 +1,128 @@ +/* GtkCheckboxPeer.java -- Implements CheckboxPeer with GTK + Copyright (C) 1998, 1999, 2002, 2003 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.Checkbox; +import java.awt.CheckboxGroup; +import java.awt.peer.CheckboxPeer; + +public class GtkCheckboxPeer extends GtkComponentPeer + implements CheckboxPeer +{ + // Group from last time it was set. + public GtkCheckboxGroupPeer old_group; + // The current state of the GTK checkbox. + private boolean currentState; + + public native void create (GtkCheckboxGroupPeer group); + public native void nativeSetCheckboxGroup (GtkCheckboxGroupPeer group); + public native void connectSignals (); + native void gtkWidgetModifyFont (String name, int style, int size); + native void gtkButtonSetLabel (String label); + native void gtkToggleButtonSetActive (boolean is_active); + + public GtkCheckboxPeer (Checkbox c) + { + super (c); + } + + // FIXME: we must be able to switch between a checkbutton and a + // radiobutton dynamically. + public void create () + { + Checkbox checkbox = (Checkbox) awtComponent; + CheckboxGroup g = checkbox.getCheckboxGroup (); + old_group = GtkCheckboxGroupPeer.getCheckboxGroupPeer (g); + create (old_group); + gtkToggleButtonSetActive (checkbox.getState ()); + gtkButtonSetLabel (checkbox.getLabel ()); + } + + public void setState (boolean state) + { + if (currentState != state) + gtkToggleButtonSetActive (state); + } + + public void setLabel (String label) + { + gtkButtonSetLabel (label); + } + + public void setCheckboxGroup (CheckboxGroup group) + { + GtkCheckboxGroupPeer gp + = GtkCheckboxGroupPeer.getCheckboxGroupPeer (group); + if (gp != old_group) + { + if (old_group != null) + old_group.remove (this); + nativeSetCheckboxGroup (gp); + old_group = gp; + } + } + + // Override the superclass postItemEvent so that the peer doesn't + // need information that we have. + public void postItemEvent (Object item, int stateChange) + { + Checkbox currentCheckBox = ((Checkbox)awtComponent); + // A firing of the event is only desired if the state has changed due to a + // button press. The currentCheckBox's state must be different from the + // one that the stateChange is changing to. + // stateChange = 1 if it goes from false -> true + // stateChange = 2 if it goes from true -> false + if (( !currentCheckBox.getState() && stateChange == 1) + || (currentCheckBox.getState() && stateChange == 2)) + { + super.postItemEvent (awtComponent, stateChange); + currentState = !currentCheckBox.getState(); + currentCheckBox.setState(currentState); + } + } + + public void dispose () + { + // Notify the group so that the native state can be cleaned up + // appropriately. + if (old_group != null) + old_group.remove (this); + super.dispose (); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java new file mode 100644 index 0000000..5028ea7 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java @@ -0,0 +1,130 @@ +/* GtkChoicePeer.java -- Implements ChoicePeer with GTK + Copyright (C) 1998, 1999, 2005 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.Choice; +import java.awt.event.ItemEvent; +import java.awt.peer.ChoicePeer; + +public class GtkChoicePeer extends GtkComponentPeer + implements ChoicePeer +{ + public GtkChoicePeer (Choice c) + { + super (c); + + int count = c.getItemCount (); + if (count > 0) + { + String items[] = new String[count]; + for (int i = 0; i < count; i++) + items[i] = c.getItem (i); + + append (items); + } + + int selected = c.getSelectedIndex(); + if (selected >= 0) + select(selected); + } + + native void create (); + + native void append (String items[]); + native int nativeGetSelected (); + native void nativeAdd (String item, int index); + native void nativeRemove (int index); + native void nativeRemoveAll (); + + native void connectSignals (); + + public native void select (int position); + + public void add (String item, int index) + { + int before = nativeGetSelected(); + + nativeAdd (item, index); + + /* Generate an ItemEvent if we added the first one or + if we inserted at or before the currently selected item. */ + if ((before < 0) || (before >= index)) + { + // Must set our state before notifying listeners + ((Choice) awtComponent).select (((Choice) awtComponent).getItem (0)); + postItemEvent (((Choice) awtComponent).getItem (0), ItemEvent.SELECTED); + } + } + + public void remove (int index) + { + int before = nativeGetSelected(); + int after; + + nativeRemove (index); + after = nativeGetSelected(); + + /* Generate an ItemEvent if we are removing the currently selected item + and there are at least one item left. */ + if ((before == index) && (after >= 0)) + { + // Must set our state before notifying listeners + ((Choice) awtComponent).select (((Choice) awtComponent).getItem (0)); + postItemEvent (((Choice) awtComponent).getItem (0), ItemEvent.SELECTED); + } + } + + public void removeAll () + { + nativeRemoveAll(); + } + + public void addItem (String item, int position) + { + add (item, position); + } + + protected void postChoiceItemEvent (String label, int stateChange) + { + // Must set our state before notifying listeners + if (stateChange == ItemEvent.SELECTED) + ((Choice) awtComponent).select (label); + postItemEvent (label, stateChange); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java new file mode 100644 index 0000000..c719cdd --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java @@ -0,0 +1,170 @@ +/* GtkClipboard.java + Copyright (C) 1999, 2005 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.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class GtkClipboard extends Clipboard +{ + /* the number of milliseconds that we'll wait around for the + owner of the GDK_SELECTION_PRIMARY selection to convert + the requested data */ + static final int SELECTION_RECEIVED_TIMEOUT = 5000; + + /* We currently only support transferring of text between applications */ + static String selection; + static Object selectionLock = new Object (); + + static boolean hasSelection = false; + + protected GtkClipboard() + { + super("System Clipboard"); + initNativeState(); + } + + public Transferable getContents(Object requestor) + { + synchronized (this) + { + if (hasSelection) + return contents; + } + + /* Java doesn't own the selection, so we need to ask X11 */ + // XXX: Does this hold with Swing too ? + synchronized (selectionLock) + { + requestStringConversion(); + + try + { + selectionLock.wait(SELECTION_RECEIVED_TIMEOUT); + } + catch (InterruptedException e) + { + return null; + } + + return selection == null ? null : new StringSelection(selection); + } + } + + void stringSelectionReceived(String newSelection) + { + synchronized (selectionLock) + { + selection = newSelection; + selectionLock.notify(); + } + } + + /* convert Java clipboard data into a String suitable for sending + to another application */ + synchronized String stringSelectionHandler() throws IOException + { + String selection = null; + + try + { + if (contents.isDataFlavorSupported(DataFlavor.stringFlavor)) + selection = (String)contents.getTransferData(DataFlavor.stringFlavor); + else if (contents.isDataFlavorSupported(DataFlavor.plainTextFlavor)) + { + StringBuffer sbuf = new StringBuffer(); + InputStreamReader reader; + char readBuf[] = new char[512]; + int numChars; + + reader = new InputStreamReader + ((InputStream) + contents.getTransferData(DataFlavor.plainTextFlavor), "UNICODE"); + + while (true) + { + numChars = reader.read(readBuf); + if (numChars == -1) + break; + sbuf.append(readBuf, 0, numChars); + } + + selection = new String(sbuf); + } + } + catch (Exception e) + { + } + + return selection; + } + + public synchronized void setContents(Transferable contents, + ClipboardOwner owner) + { + selectionGet(); + + this.contents = contents; + this.owner = owner; + + hasSelection = true; + } + + synchronized void selectionClear() + { + hasSelection = false; + + if (owner != null) + { + owner.lostOwnership(this, contents); + owner = null; + contents = null; + } + } + + native void initNativeState(); + static native void requestStringConversion(); + static native void selectionGet(); +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java new file mode 100644 index 0000000..1578a9c --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -0,0 +1,651 @@ +/* GtkComponentPeer.java -- Implements ComponentPeer with GTK + Copyright (C) 1998, 1999, 2002, 2004, 2005 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.AWTEvent; +import java.awt.AWTException; +import java.awt.BufferCapabilities; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Insets; +import java.awt.ItemSelectable; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.FocusEvent; +import java.awt.event.ItemEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.PaintEvent; +import java.awt.event.TextEvent; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.image.VolatileImage; +import java.awt.peer.ComponentPeer; + +public class GtkComponentPeer extends GtkGenericPeer + implements ComponentPeer +{ + VolatileImage backBuffer; + BufferCapabilities caps; + + Component awtComponent; + + Insets insets; + + boolean isInRepaint; + + /* this isEnabled differs from Component.isEnabled, in that it + knows if a parent is disabled. In that case Component.isEnabled + may return true, but our isEnabled will always return false */ + native boolean isEnabled (); + static native boolean modalHasGrab(); + + native int[] gtkWidgetGetForeground (); + native int[] gtkWidgetGetBackground (); + native void gtkWidgetGetDimensions (int[] dim); + native void gtkWidgetGetPreferredDimensions (int[] dim); + native void gtkWidgetGetLocationOnScreen (int[] point); + native void gtkWidgetSetCursor (int type); + native void gtkWidgetSetBackground (int red, int green, int blue); + native void gtkWidgetSetForeground (int red, int green, int blue); + native void gtkWidgetSetSensitive (boolean sensitive); + native void gtkWidgetSetParent (ComponentPeer parent); + native void gtkWidgetRequestFocus (); + native void gtkWidgetDispatchKeyEvent (int id, long when, int mods, + int keyCode, int keyLocation); + + native boolean isRealized (); + + void realize () + { + // Default implementation does nothing + } + + native void setNativeEventMask (); + + void create () + { + throw new RuntimeException (); + } + + native void connectSignals (); + + protected GtkComponentPeer (Component awtComponent) + { + super (awtComponent); + this.awtComponent = awtComponent; + insets = new Insets (0, 0, 0, 0); + + create (); + + connectSignals (); + + if (awtComponent.getForeground () != null) + setForeground (awtComponent.getForeground ()); + if (awtComponent.getBackground () != null) + setBackground (awtComponent.getBackground ()); + if (awtComponent.getFont() != null) + setFont(awtComponent.getFont()); + + Component parent = awtComponent.getParent (); + + // Only set our parent on the GTK side if our parent on the AWT + // side is not showing. Otherwise the gtk peer will be shown + // before we've had a chance to position and size it properly. + if (awtComponent instanceof Window + || (parent != null && ! parent.isShowing ())) + setParentAndBounds (); + + setNativeEventMask (); + + realize (); + } + + void setParentAndBounds () + { + setParent (); + + setComponentBounds (); + + setVisibleAndEnabled (); + } + + void setParent () + { + ComponentPeer p; + Component component = awtComponent; + do + { + component = component.getParent (); + p = component.getPeer (); + } + while (p instanceof java.awt.peer.LightweightPeer); + + if (p != null) + gtkWidgetSetParent (p); + } + + void beginNativeRepaint () + { + isInRepaint = true; + } + + void endNativeRepaint () + { + isInRepaint = false; + } + + /* + * Set the bounds of this peer's AWT Component based on dimensions + * returned by the native windowing system. Most Components impose + * their dimensions on the peers which is what the default + * implementation does. However some peers, like GtkFileDialogPeer, + * need to pass their size back to the AWT Component. + */ + void setComponentBounds () + { + Rectangle bounds = awtComponent.getBounds (); + + if (bounds.x == 0 && bounds.y == 0 + && bounds.width == 0 && bounds.height == 0) + return; + + setBounds (bounds.x, bounds.y, bounds.width, bounds.height); + } + + void setVisibleAndEnabled () + { + setVisible (awtComponent.isVisible ()); + setEnabled (awtComponent.isEnabled ()); + } + + public int checkImage (Image image, int width, int height, + ImageObserver observer) + { + return getToolkit().checkImage(image, width, height, observer); + } + + public Image createImage (ImageProducer producer) + { + return new GtkImage (producer); + } + + public Image createImage (int width, int height) + { + Image image; + if (GtkToolkit.useGraphics2D ()) + image = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB); + else + image = new GtkImage (width, height); + + Graphics g = image.getGraphics(); + g.setColor(getBackground()); + g.fillRect(0, 0, width, height); + return image; + } + + public void disable () + { + setEnabled (false); + } + + public void enable () + { + setEnabled (true); + } + + public ColorModel getColorModel () + { + return ColorModel.getRGBdefault (); + } + + public FontMetrics getFontMetrics (Font font) + { + return getToolkit().getFontMetrics(font); + } + + public Graphics getGraphics () + { + if (GtkToolkit.useGraphics2D ()) + return new GdkGraphics2D (this); + else + return new GdkGraphics (this); + } + + public Point getLocationOnScreen () + { + int point[] = new int[2]; + gtkWidgetGetLocationOnScreen (point); + return new Point (point[0], point[1]); + } + + public Dimension getMinimumSize () + { + return minimumSize (); + } + + public Dimension getPreferredSize () + { + return preferredSize (); + } + + public Toolkit getToolkit () + { + return Toolkit.getDefaultToolkit(); + } + + public void handleEvent (AWTEvent event) + { + int id = event.getID(); + KeyEvent ke = null; + + switch (id) + { + case PaintEvent.PAINT: + case PaintEvent.UPDATE: + { + try + { + Graphics g = getGraphics (); + + // Some peers like GtkFileDialogPeer are repainted by Gtk itself + if (g == null) + break; + + g.setClip (((PaintEvent) event).getUpdateRect()); + + if (id == PaintEvent.PAINT) + awtComponent.paint (g); + else + awtComponent.update (g); + + g.dispose (); + } + catch (InternalError e) + { + System.err.println (e); + } + } + break; + case KeyEvent.KEY_PRESSED: + ke = (KeyEvent) event; + gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (), + ke.getKeyCode (), ke.getKeyLocation ()); + break; + case KeyEvent.KEY_RELEASED: + ke = (KeyEvent) event; + gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (), + ke.getKeyCode (), ke.getKeyLocation ()); + break; + } + } + + public boolean isFocusTraversable () + { + return true; + } + + public Dimension minimumSize () + { + int dim[] = new int[2]; + + gtkWidgetGetPreferredDimensions (dim); + + return new Dimension (dim[0], dim[1]); + } + + public void paint (Graphics g) + { + } + + public Dimension preferredSize () + { + int dim[] = new int[2]; + + gtkWidgetGetPreferredDimensions (dim); + + return new Dimension (dim[0], dim[1]); + } + + public boolean prepareImage (Image image, int width, int height, + ImageObserver observer) + { + return getToolkit().prepareImage(image, width, height, observer); + } + + public void print (Graphics g) + { + throw new RuntimeException (); + } + + public void repaint (long tm, int x, int y, int width, int height) + { + if (x == 0 && y == 0 && width == 0 && height == 0) + return; + + q().postEvent (new PaintEvent (awtComponent, PaintEvent.UPDATE, + new Rectangle (x, y, width, height))); + } + + public void requestFocus () + { + gtkWidgetRequestFocus(); + postFocusEvent(FocusEvent.FOCUS_GAINED, false); + } + + public void reshape (int x, int y, int width, int height) + { + setBounds (x, y, width, height); + } + + public void setBackground (Color c) + { + gtkWidgetSetBackground (c.getRed(), c.getGreen(), c.getBlue()); + } + + native void setNativeBounds (int x, int y, int width, int height); + + public void setBounds (int x, int y, int width, int height) + { + Component parent = awtComponent.getParent (); + + // Heavyweight components that are children of one or more + // lightweight containers have to be handled specially. Because + // calls to GLightweightPeer.setBounds do nothing, GTK has no + // knowledge of the lightweight containers' positions. So we have + // to add the offsets manually when placing a heavyweight + // component within a lightweight container. The lightweight + // container may itself be in a lightweight container and so on, + // so we need to continue adding offsets until we reach a + // container whose position GTK knows -- that is, the first + // non-lightweight. + boolean lightweightChild = false; + Insets i; + while (parent.isLightweight ()) + { + lightweightChild = true; + + i = ((Container) parent).getInsets (); + + x += parent.getX () + i.left; + y += parent.getY () + i.top; + + parent = parent.getParent (); + } + + // We only need to convert from Java to GTK coordinates if we're + // placing a heavyweight component in a Window. + if (parent instanceof Window && !lightweightChild) + { + Insets insets = ((Window) parent).getInsets (); + GtkWindowPeer peer = (GtkWindowPeer) parent.getPeer (); + int menuBarHeight = 0; + if (peer instanceof GtkFramePeer) + menuBarHeight = ((GtkFramePeer) peer).getMenuBarHeight (); + + // Convert from Java coordinates to GTK coordinates. + setNativeBounds (x - insets.left, y - insets.top + menuBarHeight, + width, height); + } + else + setNativeBounds (x, y, width, height); + } + + void setCursor () + { + setCursor (awtComponent.getCursor ()); + } + + public void setCursor (Cursor cursor) + { + gtkWidgetSetCursor (cursor.getType ()); + } + + public void setEnabled (boolean b) + { + gtkWidgetSetSensitive (b); + } + + public void setFont (Font f) + { + // FIXME: This should really affect the widget tree below me. + // Currently this is only handled if the call is made directly on + // a text widget, which implements setFont() itself. + gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize()); + } + + public void setForeground (Color c) + { + gtkWidgetSetForeground (c.getRed(), c.getGreen(), c.getBlue()); + } + + public Color getForeground () + { + int rgb[] = gtkWidgetGetForeground (); + return new Color (rgb[0], rgb[1], rgb[2]); + } + + public Color getBackground () + { + int rgb[] = gtkWidgetGetBackground (); + return new Color (rgb[0], rgb[1], rgb[2]); + } + + public void setVisible (boolean b) + { + if (b) + show (); + else + hide (); + } + + public native void hide (); + public native void show (); + + protected void postMouseEvent(int id, long when, int mods, int x, int y, + int clickCount, boolean popupTrigger) + { + q().postEvent(new MouseEvent(awtComponent, id, when, mods, x, y, + clickCount, popupTrigger)); + } + + protected void postExposeEvent (int x, int y, int width, int height) + { + if (!isInRepaint) + q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, + new Rectangle (x, y, width, height))); + } + + protected void postKeyEvent (int id, long when, int mods, + int keyCode, char keyChar, int keyLocation) + { + KeyEvent keyEvent = new KeyEvent (awtComponent, id, when, mods, + keyCode, keyChar, keyLocation); + + // Also post a KEY_TYPED event if keyEvent is a key press that + // doesn't represent an action or modifier key. + if (keyEvent.getID () == KeyEvent.KEY_PRESSED + && (!keyEvent.isActionKey () + && keyCode != KeyEvent.VK_SHIFT + && keyCode != KeyEvent.VK_CONTROL + && keyCode != KeyEvent.VK_ALT)) + { + synchronized (q) + { + q().postEvent (keyEvent); + q().postEvent (new KeyEvent (awtComponent, KeyEvent.KEY_TYPED, when, mods, + KeyEvent.VK_UNDEFINED, keyChar, keyLocation)); + } + } + else + q().postEvent (keyEvent); + } + + protected void postFocusEvent (int id, boolean temporary) + { + q().postEvent (new FocusEvent (awtComponent, id, temporary)); + } + + protected void postItemEvent (Object item, int stateChange) + { + q().postEvent (new ItemEvent ((ItemSelectable)awtComponent, + ItemEvent.ITEM_STATE_CHANGED, + item, stateChange)); + } + + protected void postTextEvent () + { + q().postEvent (new TextEvent (awtComponent, TextEvent.TEXT_VALUE_CHANGED)); + } + + public GraphicsConfiguration getGraphicsConfiguration () + { + // FIXME: just a stub for now. + return null; + } + + public void setEventMask (long mask) + { + // FIXME: just a stub for now. + } + + public boolean isFocusable () + { + return false; + } + + public boolean requestFocus (Component source, boolean b1, + boolean b2, long x) + { + return false; + } + + public boolean isObscured () + { + return false; + } + + public boolean canDetermineObscurity () + { + return false; + } + + public void coalescePaintEvent (PaintEvent e) + { + + } + + public void updateCursorImmediately () + { + + } + + public boolean handlesWheelScrolling () + { + return false; + } + + // Convenience method to create a new volatile image on the screen + // on which this component is displayed. + public VolatileImage createVolatileImage (int width, int height) + { + return new GtkVolatileImage (width, height); + } + + // Creates buffers used in a buffering strategy. + public void createBuffers (int numBuffers, BufferCapabilities caps) + throws AWTException + { + // numBuffers == 2 implies double-buffering, meaning one back + // buffer and one front buffer. + if (numBuffers == 2) + backBuffer = new GtkVolatileImage(awtComponent.getWidth(), + awtComponent.getHeight(), + caps.getBackBufferCapabilities()); + else + throw new AWTException("GtkComponentPeer.createBuffers:" + + " multi-buffering not supported"); + this.caps = caps; + } + + // Return the back buffer. + public Image getBackBuffer () + { + return backBuffer; + } + + // FIXME: flip should be implemented as a fast native operation + public void flip (BufferCapabilities.FlipContents contents) + { + getGraphics().drawImage(backBuffer, + awtComponent.getWidth(), + awtComponent.getHeight(), + null); + + // create new back buffer and clear it to the background color. + if (contents == BufferCapabilities.FlipContents.BACKGROUND) + { + backBuffer = createVolatileImage(awtComponent.getWidth(), + awtComponent.getHeight()); + backBuffer.getGraphics().clearRect(0, 0, + awtComponent.getWidth(), + awtComponent.getHeight()); + } + // FIXME: support BufferCapabilities.FlipContents.PRIOR + } + + // Release the resources allocated to back buffers. + public void destroyBuffers () + { + backBuffer.flush(); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java new file mode 100644 index 0000000..c2865f7 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java @@ -0,0 +1,156 @@ +/* GtkContainerPeer.java -- Implements ContainerPeer with GTK + Copyright (C) 1998, 1999 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.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Window; +import java.awt.peer.ComponentPeer; +import java.awt.peer.ContainerPeer; + +public class GtkContainerPeer extends GtkComponentPeer + implements ContainerPeer +{ + Container c; + boolean isValidating; + + public GtkContainerPeer(Container c) + { + super (c); + this.c = c; + } + + public void beginValidate () + { + isValidating = true; + } + + public void endValidate () + { + Component parent = awtComponent.getParent (); + + // Only set our parent on the GTK side if our parent on the AWT + // side is not showing. Otherwise the gtk peer will be shown + // before we've had a chance to position and size it properly. + if (parent != null && parent.isShowing ()) + { + Component[] components = ((Container) awtComponent).getComponents (); + int ncomponents = components.length; + + for (int i = 0; i < ncomponents; i++) + { + ComponentPeer peer = components[i].getPeer (); + + // Skip lightweight peers. + if (peer instanceof GtkComponentPeer) + ((GtkComponentPeer) peer).setParentAndBounds (); + } + + // GTK windows don't have parents. + if (!(awtComponent instanceof Window)) + setParentAndBounds (); + } + + isValidating = false; + } + + public Insets getInsets() + { + return insets; + } + + public Insets insets() + { + return getInsets (); + } + + public void setBounds (int x, int y, int width, int height) + { + super.setBounds (x, y, width, height); + } + + public void setFont(Font f) + { + super.setFont(f); + Component[] components = ((Container) awtComponent).getComponents(); + for (int i = 0; i < components.length; i++) + { + if (components[i].isLightweight ()) + components[i].setFont (f); + else + { + GtkComponentPeer peer = (GtkComponentPeer) components[i].getPeer(); + if (peer != null && ! peer.awtComponent.isFontSet()) + peer.setFont(f); + } + } + } + + public Graphics getGraphics () + { + return super.getGraphics(); + } + + public void beginLayout () { } + public void endLayout () { } + public boolean isPaintPending () { return false; } + + public void setBackground (Color c) + { + super.setBackground(c); + + Object components[] = ((Container) awtComponent).getComponents(); + for (int i = 0; i < components.length; i++) + { + Component comp = (Component) components[i]; + + // If the child's background has not been explicitly set yet, + // it should inherit this container's background. This makes the + // child component appear as if it has a transparent background. + // Note that we do not alter the background property of the child, + // but only repaint the child with the parent's background color. + if (!comp.isBackgroundSet() && comp.getPeer() != null) + comp.getPeer().setBackground(c); + } + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkDialogPeer.java new file mode 100644 index 0000000..c2cbc37 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkDialogPeer.java @@ -0,0 +1,94 @@ +/* GtkDialogPeer.java -- Implements DialogPeer with GTK + Copyright (C) 1998, 1999, 2002 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.Dialog; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.event.PaintEvent; +import java.awt.peer.DialogPeer; + +public class GtkDialogPeer extends GtkWindowPeer + implements DialogPeer +{ + public GtkDialogPeer (Dialog dialog) + { + super (dialog); + } + + public Graphics getGraphics () + { + Graphics g; + if (GtkToolkit.useGraphics2D ()) + g = new GdkGraphics2D (this); + else + g = new GdkGraphics (this); + g.translate (-insets.left, -insets.top); + return g; + } + + protected void postMouseEvent(int id, long when, int mods, int x, int y, + int clickCount, boolean popupTrigger) + { + super.postMouseEvent (id, when, mods, + x + insets.left, y + insets.top, + clickCount, popupTrigger); + } + + protected void postExposeEvent (int x, int y, int width, int height) + { + if (!isInRepaint) + q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, + new Rectangle (x + insets.left, + y + insets.top, + width, height))); + } + + void create () + { + // Create a decorated dialog window. + create (GDK_WINDOW_TYPE_HINT_DIALOG, true); + + Dialog dialog = (Dialog) awtComponent; + + gtkWindowSetModal (dialog.isModal ()); + setTitle (dialog.getTitle ()); + setResizable (dialog.isResizable ()); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkEmbeddedWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkEmbeddedWindowPeer.java new file mode 100644 index 0000000..0533d27 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkEmbeddedWindowPeer.java @@ -0,0 +1,73 @@ +/* GtkEmbeddedWindowPeer.java -- Implements EmbeddedWindowPeer using a + GtkPlug + Copyright (C) 2003 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.EmbeddedWindow; +import gnu.java.awt.peer.EmbeddedWindowPeer; + +public class GtkEmbeddedWindowPeer extends GtkFramePeer + implements EmbeddedWindowPeer +{ + native void create (long socket_id); + + void create () + { + create (((EmbeddedWindow) awtComponent).getHandle ()); + } + + native void construct (long socket_id); + + // FIXME: embed doesn't work right now, though I believe it should. + // This means that you can't call setVisible (true) on an + // EmbeddedWindow before calling setHandle with a valid handle. The + // problem is that somewhere after the call to + // GtkEmbeddedWindow.create and before the call to + // GtkEmbeddedWindow.construct, the GtkPlug peer is being realized. + // GtkSocket silently fails to embed an already-realized GtkPlug. + public void embed (long handle) + { + construct (handle); + } + + public GtkEmbeddedWindowPeer (EmbeddedWindow w) + { + super (w); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java new file mode 100644 index 0000000..bd1f077 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java @@ -0,0 +1,219 @@ +/* GtkFileDialogPeer.java -- Implements FileDialogPeer with GTK + Copyright (C) 1998, 1999, 2002, 2004, 2005 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.Dialog; +import java.awt.FileDialog; +import java.awt.Graphics; +import java.awt.Window; +import java.awt.peer.FileDialogPeer; +import java.io.File; +import java.io.FilenameFilter; + +public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer +{ + static final String FS = System.getProperty("file.separator"); + + private String currentFile = null; + private String currentDirectory = null; + private FilenameFilter filter; + + native void create (GtkContainerPeer parent); + native void connectSignals (); + native void nativeSetFile (String file); + public native String nativeGetDirectory(); + public native void nativeSetDirectory(String directory); + native void nativeSetFilenameFilter (FilenameFilter filter); + + public void create() + { + create((GtkContainerPeer) awtComponent.getParent().getPeer()); + + FileDialog fd = (FileDialog) awtComponent; + + setDirectory(fd.getDirectory()); + setFile(fd.getFile()); + + FilenameFilter filter = fd.getFilenameFilter(); + if (filter != null) + setFilenameFilter(filter); + } + + public GtkFileDialogPeer (FileDialog fd) + { + super (fd); + } + + void setComponentBounds () + { + if (awtComponent.getHeight () == 0 + && awtComponent.getWidth () == 0) + { + int[] dims = new int[2]; + gtkWidgetGetPreferredDimensions (dims); + ((GtkFileDialogPeer) this).setBoundsCallback ((Window) awtComponent, + awtComponent.getX (), + awtComponent.getY (), + dims[0], dims[1]); + } + super.setComponentBounds (); + } + + public void setFile (String fileName) + { + /* If nothing changed do nothing. This usually happens because + the only way we have to set the file name in FileDialog is by + calling its SetFile which will call us back. */ + if ((fileName == null && currentFile == null) + || (fileName != null && fileName.equals (currentFile))) + return; + + if (fileName == null || fileName.equals ("")) + { + currentFile = ""; + nativeSetFile (""); + return; + } + + // GtkFileChooser requires absolute filenames. If the given filename + // is not absolute, let's construct it based on current directory. + currentFile = fileName; + if (fileName.indexOf(FS) == 0) + { + nativeSetFile (fileName); + } + else + { + nativeSetFile (nativeGetDirectory() + FS + fileName); + } + } + + public void setDirectory (String directory) + { + /* If nothing changed so nothing. This usually happens because + the only way we have to set the directory in FileDialog is by + calling its setDirectory which will call us back. */ + if ((directory == null && currentDirectory == null) + || (directory != null && directory.equals (currentDirectory))) + return; + + if (directory == null || directory.equals ("")) + { + currentDirectory = FS; + nativeSetFile (FS); + return; + } + + currentDirectory = directory; + nativeSetDirectory (directory); + } + + public void setFilenameFilter (FilenameFilter filter) + { + this.filter = filter; + nativeSetFilenameFilter(filter); + } + + /* This method interacts with the native callback function of the + same name. The native function will extract the filename from the + GtkFileFilterInfo object and send it to this method, which will + in turn call the filter's accept() method and give back the return + value. */ + boolean filenameFilterCallback (String fullname) { + String filename = fullname.substring(fullname.lastIndexOf(FS) + 1); + String dirname = fullname.substring(0, fullname.lastIndexOf(FS)); + File dir = new File(dirname); + return filter.accept(dir, filename); + } + + public Graphics getGraphics () + { + // GtkFileDialog will repaint by itself + return null; + } + + void gtkHideFileDialog () + { + ((Dialog) awtComponent).hide(); + } + + void gtkDisposeFileDialog () + { + ((Dialog) awtComponent).dispose(); + } + + /* Callback to set the file and directory values when the user is finished + * with the dialog. + */ + void gtkSetFilename (String fileName) + { + FileDialog fd = (FileDialog) awtWidget; + if (fileName == null) + { + currentFile = null; + fd.setFile(null); + return; + } + + int sepIndex = fileName.lastIndexOf (FS); + if (sepIndex < 0) + { + /* This should never happen on Unix (all paths start with '/') */ + currentFile = fileName; + } + else + { + if (fileName.length() > (sepIndex + 1)) + { + String fn = fileName.substring (sepIndex + 1); + currentFile = fn; + } + else + { + currentFile = null; + } + + String dn = fileName.substring (0, sepIndex + 1); + currentDirectory = dn; + fd.setDirectory(dn); + } + + fd.setFile (currentFile); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFontPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFontPeer.java new file mode 100644 index 0000000..80ad158 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFontPeer.java @@ -0,0 +1,225 @@ +/* GtkFontPeer.java -- Implements FontPeer with GTK+ + Copyright (C) 1999, 2004, 2005 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.peer.ClasspathFontPeer; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineMetrics; +import java.awt.geom.Rectangle2D; +import java.text.CharacterIterator; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class GtkFontPeer extends ClasspathFontPeer +{ + private static ResourceBundle bundle; + + static + { + try + { + bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font"); + } + catch (Throwable ignored) + { + bundle = null; + } + } + + private final String Xname; + + public GtkFontPeer (String name, int style) + { + // All fonts get a default size of 12 if size is not specified. + this(name, style, 12); + } + + public GtkFontPeer (String name, int style, int size) + { + super(name, style, size); + + String Xname = null; + if (bundle != null) + { + try + { + Xname = bundle.getString (name.toLowerCase () + "." + style); + } + catch (MissingResourceException mre) + { + // ignored + } + } + + if (Xname == null) + { + String weight; + String slant; + String spacing; + + if (style == Font.ITALIC || (style == (Font.BOLD+Font.ITALIC))) + slant = "i"; + else + slant = "r"; + if (style == Font.BOLD || (style == (Font.BOLD+Font.ITALIC))) + weight = "bold"; + else + weight = "medium"; + if (name.equals("Serif") || name.equals("SansSerif") + || name.equals("Helvetica") || name.equals("Times")) + spacing = "p"; + else + spacing = "c"; + + Xname = "-*-*-" + weight + "-" + slant + "-normal-*-*-" + size + "-*-*-" + spacing + "-*-*-*"; + } + + this.Xname = Xname; + } + + public String getXLFD () + { + return Xname; + } + + + /* remaining methods are for static compatibility with the newer + ClasspathFontPeer superclass; none of these methods ever existed or + worked on the older FontPeer interface, but we need to pretend to + support them anyways. */ + + public boolean canDisplay (Font font, char c) + { + throw new UnsupportedOperationException(); + } + + public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit) + { + throw new UnsupportedOperationException(); + } + + public String getSubFamilyName (Font font, Locale locale) + { + throw new UnsupportedOperationException(); + } + + public String getPostScriptName (Font font) + { + throw new UnsupportedOperationException(); + } + + public int getNumGlyphs (Font font) + { + throw new UnsupportedOperationException(); + } + + public int getMissingGlyphCode (Font font) + { + throw new UnsupportedOperationException(); + } + + public byte getBaselineFor (Font font, char c) + { + throw new UnsupportedOperationException(); + } + + public String getGlyphName (Font font, int glyphIndex) + { + throw new UnsupportedOperationException(); + } + + public GlyphVector createGlyphVector (Font font, + FontRenderContext frc, + CharacterIterator ci) + { + throw new UnsupportedOperationException(); + } + + public GlyphVector createGlyphVector (Font font, + FontRenderContext ctx, + int[] glyphCodes) + { + throw new UnsupportedOperationException(); + } + + public GlyphVector layoutGlyphVector (Font font, + FontRenderContext frc, + char[] chars, int start, + int limit, int flags) + { + throw new UnsupportedOperationException(); + } + + public FontMetrics getFontMetrics (Font font) + { + throw new UnsupportedOperationException(); + } + + public boolean hasUniformLineMetrics (Font font) + { + throw new UnsupportedOperationException(); + } + + public LineMetrics getLineMetrics (Font font, + CharacterIterator ci, + int begin, int limit, + FontRenderContext rc) + { + throw new UnsupportedOperationException(); + } + + public Rectangle2D getMaxCharBounds (Font font, + FontRenderContext rc) + { + throw new UnsupportedOperationException(); + } + + public Rectangle2D getStringBounds (Font font, + CharacterIterator ci, + int begin, int limit, + FontRenderContext frc) + { + throw new UnsupportedOperationException(); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java new file mode 100644 index 0000000..b242d66 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java @@ -0,0 +1,256 @@ +/* GtkFramePeer.java -- Implements FramePeer with GTK + Copyright (C) 1999, 2002, 2004 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.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.MenuBar; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.PaintEvent; +import java.awt.image.ColorModel; +import java.awt.peer.FramePeer; +import java.awt.peer.MenuBarPeer; + +public class GtkFramePeer extends GtkWindowPeer + implements FramePeer +{ + private int menuBarHeight; + private MenuBarPeer menuBar; + native int getMenuBarHeight (MenuBarPeer bar); + native void setMenuBarWidth (MenuBarPeer bar, int width); + native void setMenuBarPeer (MenuBarPeer bar); + native void removeMenuBarPeer (); + native void gtkFixedSetVisible (boolean visible); + + int getMenuBarHeight () + { + return menuBar == null ? 0 : getMenuBarHeight (menuBar); + } + + public void setMenuBar (MenuBar bar) + { + if (bar == null && menuBar != null) + { + // We're removing the menubar. + gtkFixedSetVisible (false); + menuBar = null; + removeMenuBarPeer (); + insets.top -= menuBarHeight; + menuBarHeight = 0; + awtComponent.validate (); + gtkFixedSetVisible (true); + } + else if (bar != null && menuBar == null) + { + // We're adding a menubar where there was no menubar before. + gtkFixedSetVisible (false); + menuBar = (MenuBarPeer) ((MenuBar) bar).getPeer(); + setMenuBarPeer (menuBar); + int menuBarWidth = + awtComponent.getWidth () - insets.left - insets.right; + if (menuBarWidth > 0) + setMenuBarWidth (menuBar, menuBarWidth); + menuBarHeight = getMenuBarHeight (); + insets.top += menuBarHeight; + awtComponent.validate (); + gtkFixedSetVisible (true); + } + else if (bar != null && menuBar != null) + { + // We're swapping the menubar. + gtkFixedSetVisible (false); + removeMenuBarPeer(); + int oldHeight = menuBarHeight; + int menuBarWidth = + awtComponent.getWidth () - insets.left - insets.right; + menuBar = (MenuBarPeer) ((MenuBar) bar).getPeer (); + setMenuBarPeer (menuBar); + if (menuBarWidth > 0) + setMenuBarWidth (menuBar, menuBarWidth); + menuBarHeight = getMenuBarHeight (); + if (oldHeight != menuBarHeight) + { + insets.top += (menuBarHeight - oldHeight); + awtComponent.validate (); + } + gtkFixedSetVisible (true); + } + } + + public void setBounds (int x, int y, int width, int height) + { + int menuBarWidth = width - insets.left - insets.right; + if (menuBar != null && menuBarWidth > 0) + setMenuBarWidth (menuBar, menuBarWidth); + + nativeSetBounds (x, y, + width - insets.left - insets.right, + height - insets.top - insets.bottom + + menuBarHeight); + } + + public void setResizable (boolean resizable) + { + // Call setSize; otherwise when resizable is changed from true to + // false the frame will shrink to the dimensions it had before it + // was resizable. + setSize (awtComponent.getWidth() - insets.left - insets.right, + awtComponent.getHeight() - insets.top - insets.bottom + + menuBarHeight); + gtkWindowSetResizable (resizable); + } + + protected void postInsetsChangedEvent (int top, int left, + int bottom, int right) + { + insets.top = top + menuBarHeight; + insets.left = left; + insets.bottom = bottom; + insets.right = right; + } + + public GtkFramePeer (Frame frame) + { + super (frame); + } + + void create () + { + // Create a normal decorated window. + create (GDK_WINDOW_TYPE_HINT_NORMAL, true); + + Frame frame = (Frame) awtComponent; + + setMenuBar (frame.getMenuBar ()); + + setTitle (frame.getTitle ()); + gtkWindowSetResizable (frame.isResizable ()); + setIconImage(frame.getIconImage()); + } + + native void nativeSetIconImage (GtkImage image); + + public void setIconImage (Image image) + { + if (image != null) + { + if (image instanceof GtkImage) + nativeSetIconImage((GtkImage) image); + else + nativeSetIconImage(new GtkImage(image.getSource())); + } + } + + public Graphics getGraphics () + { + Graphics g; + if (GtkToolkit.useGraphics2D ()) + g = new GdkGraphics2D (this); + else + g = new GdkGraphics (this); + g.translate (-insets.left, -insets.top); + return g; + } + + protected void postConfigureEvent (int x, int y, int width, int height) + { + int frame_x = x - insets.left; + // Since insets.top includes the MenuBar height, we need to add back + // the MenuBar height to the frame's y position. + // If no MenuBar exists in this frame, the MenuBar height will be 0. + int frame_y = y - insets.top + menuBarHeight; + int frame_width = width + insets.left + insets.right; + // Ditto as above. Since insets.top already includes the MenuBar's height, + // we need to subtract the MenuBar's height from the top inset. + int frame_height = height + insets.top + insets.bottom - menuBarHeight; + if (frame_x != awtComponent.getX() + || frame_y != awtComponent.getY() + || frame_width != awtComponent.getWidth() + || frame_height != awtComponent.getHeight()) + { + if (frame_width != awtComponent.getWidth() && menuBar != null + && width > 0) + setMenuBarWidth (menuBar, width); + + setBoundsCallback ((Window) awtComponent, + frame_x, + frame_y, + frame_width, + frame_height); + + awtComponent.validate(); + } + } + + protected void postMouseEvent(int id, long when, int mods, int x, int y, + int clickCount, boolean popupTrigger) + { + super.postMouseEvent (id, when, mods, + x + insets.left, y + insets.top, + clickCount, popupTrigger); + } + + protected void postExposeEvent (int x, int y, int width, int height) + { + if (!isInRepaint) + q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, + new Rectangle (x + insets.left, + y + insets.top, + width, height))); + } + + public int getState () + { + return 0; + } + + public void setState (int state) + { + + } + + public void setMaximizedBounds (Rectangle r) + { + + } +} + + diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java new file mode 100644 index 0000000..705eed2 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java @@ -0,0 +1,98 @@ +/* GtkGenericPeer.java - Has a hashcode. Yuck. + Copyright (C) 1998, 1999, 2002 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.EventQueue; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; + +public class GtkGenericPeer +{ + final int native_state = getUniqueInteger (); + + // Next native state value we will assign. + private static int next_native_state = 0; + + // The widget or other java-side object we wrap. + protected Object awtWidget; + + // Global event queue. + protected static EventQueue q = null; + + // Dispose of our native state. + public native void dispose (); + + static EventQueue q () + { + return Toolkit.getDefaultToolkit ().getSystemEventQueue (); + } + + protected GtkGenericPeer (Object awtWidget) + { + this.awtWidget = awtWidget; + } + + public static void enableQueue (EventQueue sq) + { + if (q == null) + q = sq; + } + + protected void postActionEvent (String command, int mods) + { + q().postEvent (new ActionEvent (awtWidget, ActionEvent.ACTION_PERFORMED, + command, mods)); + } + + // Return a unique integer for use in the native state mapping + // code. We can't use a hash code since that is not guaranteed to + // be unique. + static synchronized int getUniqueInteger () + { + // Let's assume this will never wrap. + return next_native_state++; + } + + native void gtkWidgetModifyFont (String name, int style, int size); + + static void printCurrentThread () + { + System.out.println ("gtkgenericpeer, thread: " + Thread.currentThread ()); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java new file mode 100644 index 0000000..abb4137 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java @@ -0,0 +1,494 @@ +/* GtkImage.java + Copyright (C) 2005 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.Graphics; +import java.awt.Color; +import java.awt.Image; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.MemoryImageSource; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.io.File; +import java.io.IOException; +import java.util.Hashtable; +import java.util.Vector; +import gnu.classpath.RawData; + +/** + * GtkImage - wraps a GdkPixbuf or GdkPixmap. + * + * The constructor GtkImage(int, int) creates an 'off-screen' GdkPixmap, + * this can be drawn to (it's a GdkDrawable), and correspondingly, you can + * create a GdkGraphics object for it. + * + * This corresponds to the Image implementation returned by + * Component.createImage(int, int). + * + * A GdkPixbuf is 'on-screen' and the gdk cannot draw to it, + * this is used for the other constructors (and other createImage methods), and + * corresponds to the Image implementations returned by the Toolkit.createImage + * methods, and is basically immutable. + * + * @author Sven de Marothy + */ +public class GtkImage extends Image +{ + int width = -1, height = -1; + + /** + * Properties. + */ + Hashtable props; + + /** + * Loaded or not flag, for asynchronous compatibility. + */ + boolean isLoaded; + + /** + * Pointer to the GdkPixbuf + */ + RawData pixmap; + + /** + * Observer queue. + */ + Vector observers; + + /** + * If offScreen is set, a GdkBitmap is wrapped and not a Pixbuf. + */ + boolean offScreen; + + /** + * Error flag for loading. + */ + boolean errorLoading; + + /** + * Original source, if created from an ImageProducer. + */ + ImageProducer source; + + /* + * The 32-bit AABBGGRR format the GDK uses. + */ + static ColorModel nativeModel = new DirectColorModel(32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); + + /** + * Returns a copy of the pixel data as a java array. + */ + private native int[] getPixels(); + + /** + * Sets the pixel data from a java array. + */ + private native void setPixels(int[] pixels); + + /** + * Loads an image using gdk-pixbuf. + */ + private native boolean loadPixbuf(String name); + + /** + * Allocates a Gtk Pixbuf or pixmap + */ + private native void createPixmap(); + + /** + * Frees the above. + */ + private native void freePixmap(); + + /** + * Sets the pixmap to scaled copy of src image. hints are rendering hints. + */ + private native void createScaledPixmap(GtkImage src, int hints); + + /** + * Draws the image, optionally scaled and composited. + */ + private native void drawPixelsScaled (GdkGraphics gc, + int bg_red, int bg_green, int bg_blue, + int x, int y, int width, int height, + boolean composite); + + /** + * Draws the image, optionally scaled flipped and composited. + */ + private native void drawPixelsScaledFlipped (GdkGraphics gc, + int bg_red, int bg_green, + int bg_blue, + boolean flipX, boolean flipY, + int srcX, int srcY, + int srcWidth, int srcHeight, + int dstX, int dstY, + int dstWidth, int dstHeight, + boolean composite); + + /** + * Constructs a GtkImage from an ImageProducer. Asynchronity is handled in + * the following manner: + * A GtkImageConsumer gets the image data, and calls setImage() when + * completely finished. The GtkImage is not considered loaded until the + * GtkImageConsumer is completely finished. We go for all "all or nothing". + */ + public GtkImage (ImageProducer producer) + { + isLoaded = false; + observers = new Vector(); + source = producer; + errorLoading = false; + source.startProduction(new GtkImageConsumer(this, source)); + offScreen = false; + } + + /** + * Constructs a GtkImage by loading a given file. + * + * @throws IllegalArgumentException if the image could not be loaded. + */ + public GtkImage (String filename) + { + File f = new File(filename); + try + { + if (loadPixbuf(f.getCanonicalPath()) != true) + throw new IllegalArgumentException("Couldn't load image: "+filename); + } + catch(IOException e) + { + throw new IllegalArgumentException("Couldn't load image: "+filename); + } + + isLoaded = true; + observers = null; + offScreen = false; + props = new Hashtable(); + } + + /** + * Constructs an empty GtkImage. + */ + public GtkImage (int width, int height) + { + this.width = width; + this.height = height; + props = new Hashtable(); + isLoaded = true; + observers = null; + offScreen = true; + createPixmap(); + } + + /** + * Constructs a scaled version of the src bitmap, using the GDK. + */ + private GtkImage (GtkImage src, int width, int height, int hints) + { + this.width = width; + this.height = height; + props = new Hashtable(); + isLoaded = true; + observers = null; + offScreen = false; + + // Use the GDK scaling method. + createScaledPixmap(src, hints); + } + + /** + * Callback from the image consumer. + */ + public void setImage(int width, int height, + int[] pixels, Hashtable properties) + { + this.width = width; + this.height = height; + props = (properties != null) ? properties : new Hashtable(); + + if (width <= 0 || height <= 0 || pixels == null) + { + errorLoading = true; + return; + } + + isLoaded = true; + deliver(); + createPixmap(); + setPixels(pixels); + } + + // java.awt.Image methods //////////////////////////////////////////////// + + public synchronized int getWidth (ImageObserver observer) + { + if (addObserver(observer)) + return -1; + + return width; + } + + public synchronized int getHeight (ImageObserver observer) + { + if (addObserver(observer)) + return -1; + + return height; + } + + public synchronized Object getProperty (String name, ImageObserver observer) + { + if (addObserver(observer)) + return UndefinedProperty; + + Object value = props.get (name); + return (value == null) ? UndefinedProperty : value; + } + + /** + * Returns the source of this image. + */ + public ImageProducer getSource () + { + if (!isLoaded) + return null; + return new MemoryImageSource(width, height, nativeModel, getPixels(), + 0, width); + } + + /** + * Creates a GdkGraphics context for this pixmap. + */ + public Graphics getGraphics () + { + if (!isLoaded) + return null; + if (offScreen) + return new GdkGraphics(this); + else + throw new IllegalAccessError("This method only works for off-screen" + +" Images."); + } + + /** + * Returns a scaled instance of this pixmap. + */ + public Image getScaledInstance(int width, + int height, + int hints) + { + if (width <= 0 || height <= 0) + throw new IllegalArgumentException("Width and height of scaled bitmap"+ + "must be >= 0"); + + return new GtkImage(this, width, height, hints); + } + + /** + * If the image is loaded and comes from an ImageProducer, + * regenerate the image from there. + * + * I have no idea if this is ever actually used. Since GtkImage can't be + * instantiated directly, how is the user to know if it was created from + * an ImageProducer or not? + */ + public synchronized void flush () + { + if (isLoaded && source != null) + { + observers = new Vector(); + isLoaded = false; + freePixmap(); + source.startProduction(new GtkImageConsumer(this, source)); + } + } + + public void finalize() + { + if (isLoaded) + freePixmap(); + } + + /** + * Returns the image status, used by GtkToolkit + */ + public int checkImage (ImageObserver observer) + { + if (addObserver(observer)) + { + if (errorLoading == true) + return ImageObserver.ERROR; + else + return 0; + } + + return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT; + } + + // Drawing methods //////////////////////////////////////////////// + + /** + * Draws an image with eventual scaling/transforming. + */ + public boolean drawImage (GdkGraphics g, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + Color bgcolor, ImageObserver observer) + { + if (addObserver(observer)) + return false; + + boolean flipX = (dx1 > dx2)^(sx1 > sx2); + boolean flipY = (dy1 > dy2)^(sy1 > sy2); + int dstWidth = Math.abs (dx2 - dx1); + int dstHeight = Math.abs (dy2 - dy1); + int srcWidth = Math.abs (sx2 - sx1); + int srcHeight = Math.abs (sy2 - sy1); + int srcX = (sx1 < sx2) ? sx1 : sx2; + int srcY = (sy1 < sy2) ? sy1 : sy2; + int dstX = (dx1 < dx2) ? dx1 : dx2; + int dstY = (dy1 < dy2) ? dy1 : dy2; + + // Clipping. This requires the dst to be scaled as well, + if (srcWidth > width) + { + dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth)); + srcWidth = width - srcX; + } + + if (srcHeight > height) + { + dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight)); + srcHeight = height - srcY; + } + + if (srcWidth + srcX > width) + { + dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth); + srcWidth = width - srcX; + } + + if (srcHeight + srcY > height) + { + dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight); + srcHeight = height - srcY; + } + + if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0) + return true; + + if(bgcolor != null) + drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (), + bgcolor.getBlue (), + flipX, flipY, + srcX, srcY, + srcWidth, srcHeight, + dstX, dstY, + dstWidth, dstHeight, + true); + else + drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY, + srcX, srcY, srcWidth, srcHeight, + dstX, dstY, dstWidth, dstHeight, + false); + return true; + } + + /** + * Draws an image to the GdkGraphics context, at (x,y) scaled to + * width and height, with optional compositing with a background color. + */ + public boolean drawImage (GdkGraphics g, int x, int y, int width, int height, + Color bgcolor, ImageObserver observer) + { + if (addObserver(observer)) + return false; + + if(bgcolor != null) + drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (), + bgcolor.getBlue (), x, y, width, height, true); + else + drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false); + + return true; + } + + // Private methods //////////////////////////////////////////////// + + /** + * Delivers notifications to all queued observers. + */ + private void deliver() + { + int flags = ImageObserver.HEIGHT | + ImageObserver.WIDTH | + ImageObserver.PROPERTIES | + ImageObserver.ALLBITS; + + if (observers != null) + for(int i=0; i < observers.size(); i++) + ((ImageObserver)observers.elementAt(i)). + imageUpdate(this, flags, 0, 0, width, height); + + observers = null; + } + + /** + * Adds an observer, if we need to. + * @return true if an observer was added. + */ + private boolean addObserver(ImageObserver observer) + { + if (!isLoaded) + { + if(observer != null) + if (!observers.contains (observer)) + observers.addElement (observer); + return true; + } + return false; + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java new file mode 100644 index 0000000..564cc8d --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java @@ -0,0 +1,155 @@ +/* GtkImageConsumer.java + Copyright (C) 2005 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.Graphics; +import java.awt.Image; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.util.Hashtable; +import java.util.Vector; + +/** + * Helper class to GtkImage. Sits and gathers pixels for a GtkImage and then + * calls GtkImage.setImage(). + * + * @author Sven de Marothy + */ +public class GtkImageConsumer implements ImageConsumer +{ + private GtkImage target; + private int width, height; + private Hashtable properties; + private int[] pixelCache = null; + private ImageProducer source; + + public GtkImageConsumer(GtkImage target, ImageProducer source) + { + this.target = target; + this.source = source; + } + + public synchronized void imageComplete (int status) + { + source.removeConsumer(this); + target.setImage(width, height, pixelCache, properties); + } + + public synchronized void setColorModel (ColorModel model) + { + // This method is to inform on what the most used color model + // in the image is, for optimization reasons. We ignore this + // information. + } + + public synchronized void setDimensions (int width, int height) + { + pixelCache = new int[width*height]; + + this.width = width; + this.height = height; + } + + public synchronized void setHints (int flags) + { + // This method informs us in which order the pixels are + // delivered, for progressive-loading support, etc. + // Since we wait until it's all loaded, we can ignore the hints. + } + + public synchronized void setPixels (int x, int y, int width, int height, + ColorModel cm, byte[] pixels, + int offset, int scansize) + { + setPixels (x, y, width, height, cm, convertPixels (pixels), offset, + scansize); + } + + public synchronized void setPixels (int x, int y, int width, int height, + ColorModel cm, int[] pixels, + int offset, int scansize) + { + if (pixelCache == null) + return; // Not sure this should ever happen. + + if (cm.equals(GtkImage.nativeModel)) + for (int i = 0; i < height; i++) + System.arraycopy (pixels, offset + (i * scansize), + pixelCache, (y + i) * this.width + x, + width); + else + { + for (int i = 0; i < height; i++) + for (int j = 0; j < width; j++) + { + // get in AARRGGBB and convert to AABBGGRR + int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]); + byte b = (byte)(pix & 0xFF); + byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF); + pix &= 0xFF00FF00; + pix |= ((b & 0xFF) << 16); + pix |= (r & 0xFF); + pixelCache[(y + i) * this.width + x + j] = pix; + } + } + } + + /** + * This is an old method, no idea if it's correct. + */ + private int[] convertPixels (byte[] pixels) + { + int ret[] = new int[pixels.length]; + + for (int i = 0; i < pixels.length; i++) + ret[i] = pixels[i] & 0xFF; + + return ret; + } + + public synchronized void setProperties (Hashtable props) + { + this.properties = props; + } +} + + diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java new file mode 100644 index 0000000..fdd5fd1 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java @@ -0,0 +1,84 @@ +/* GtkLabelPeer.java -- Implements LabelPeer with GTK + Copyright (C) 1998, 1999, 2005 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.Label; +import java.awt.peer.LabelPeer; + +public class GtkLabelPeer extends GtkComponentPeer + implements LabelPeer +{ + native void create (String text, float alignment); + native void gtkWidgetModifyFont (String name, int style, int size); + native void nativeSetAlignment (float alignment); + + public native void setText(String text); + native void setNativeBounds (int x, int y, int width, int height); + + void create () + { + Label label = (Label) awtComponent; + create (label.getText (), getGtkAlignment (label.getAlignment ())); + } + + public GtkLabelPeer (Label l) + { + super (l); + } + + public void setAlignment (int alignment) + { + nativeSetAlignment (getGtkAlignment (alignment)); + } + + float getGtkAlignment (int alignment) + { + switch (alignment) + { + case Label.LEFT: + return 0.0f; + case Label.CENTER: + return 0.5f; + case Label.RIGHT: + return 1.0f; + } + + return 0.0f; + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java new file mode 100644 index 0000000..ff12fe3 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java @@ -0,0 +1,180 @@ +/* GtkListPeer.java -- Implements ListPeer with GTK + Copyright (C) 1998, 1999 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.AWTEvent; +import java.awt.Dimension; +import java.awt.List; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.peer.ListPeer; + +public class GtkListPeer extends GtkComponentPeer + implements ListPeer +{ + void create () + { + List list = (List) awtComponent; + + create (list.getRows ()); + + setMultipleMode (list.isMultipleMode ()); + } + + native void create (int rows); + native void connectSignals (); + native void gtkWidgetModifyFont (String name, int style, int size); + native void gtkWidgetRequestFocus (); + + native void getSize (int rows, int visibleRows, int dims[]); + + public GtkListPeer (List list) + { + super (list); + + setMultipleMode (list.isMultipleMode ()); + + if (list.getItemCount () > 0) + append (list.getItems ()); + } + + native void append (String items[]); + + public native void add (String item, int index); + + public void addItem (String item, int index) + { + add (item, index); + } + + public void clear () + { + removeAll (); + } + + public native void delItems (int start, int end); + public native void deselect (int index); + + public Dimension getMinimumSize (int rows) + { + return minimumSize (rows); + } + + public Dimension getPreferredSize (int rows) + { + return preferredSize (rows); + } + + public native int[] getSelectedIndexes (); + public native void makeVisible (int index); + + public Dimension minimumSize (int rows) + { + int dims[] = new int[2]; + + int visibleRows = ((List) awtComponent).getRows(); + getSize (rows, visibleRows, dims); + return new Dimension (dims[0], dims[1]); + } + + public Dimension preferredSize (int rows) + { + int dims[] = new int[2]; + + int visibleRows = ((List) awtComponent).getRows(); + getSize (rows, visibleRows, dims); + return new Dimension (dims[0], dims[1]); + } + + public void removeAll () + { + delItems (0, -1); + } + + public native void select (int index); + public native void setMultipleMode (boolean b); + + public void setMultipleSelections (boolean b) + { + setMultipleMode (b); + } + + public void handleEvent (AWTEvent e) + { + if (e.getID () == MouseEvent.MOUSE_CLICKED && isEnabled ()) + { + // Only generate the ActionEvent on the second click of a + // multiple click. + MouseEvent me = (MouseEvent) e; + if (!me.isConsumed () + && (me.getModifiersEx () & MouseEvent.BUTTON1_DOWN_MASK) != 0 + && me.getClickCount() == 2) + { + String selectedItem = ((List) awtComponent).getSelectedItem (); + + // Double-click only generates an Action event if + // something is selected. + if (selectedItem != null) + postActionEvent (((List) awtComponent).getSelectedItem (), + me.getModifiersEx ()); + } + } + + if (e.getID () == KeyEvent.KEY_PRESSED) + { + KeyEvent ke = (KeyEvent) e; + if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_ENTER) + { + String selectedItem = ((List) awtComponent).getSelectedItem (); + + // Enter only generates an Action event if something is + // selected. + if (selectedItem != null) + postActionEvent (selectedItem, ke.getModifiersEx ()); + } + } + + super.handleEvent (e); + } + + protected void postItemEvent (int item, int stateChange) + { + postItemEvent (new Integer (item), stateChange); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java new file mode 100644 index 0000000..79eeaf9 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java @@ -0,0 +1,80 @@ +/* GtkMenuBarPeer.java -- Implements MenuBarPeer with GTK+ + Copyright (C) 1999, 2005 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.Font; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuComponent; +import java.awt.peer.MenuBarPeer; +import java.awt.peer.MenuPeer; + +public class GtkMenuBarPeer extends GtkMenuComponentPeer + implements MenuBarPeer +{ + + native void create (); + native void addMenu (MenuPeer menu); + + public GtkMenuBarPeer (MenuBar target) + { + super (target); + } + + void setFont () + { + MenuComponent mc = (MenuComponent) awtWidget; + Font f = mc.getFont (); + + if (f == null) + mc.setFont (new Font ("Dialog", Font.PLAIN, 12)); + } + + // FIXME: remove this method or replace it with one that does + // something useful. + /* In Gnome, help menus are no longer right flushed. */ + native void nativeSetHelpMenu(MenuPeer menuPeer); + + public void addHelpMenu (Menu menu) + { + // nativeSetHelpMenu((MenuPeer) menu.getPeer()); + } + + public native void delMenu(int index); +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java new file mode 100644 index 0000000..8d9d1ca --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java @@ -0,0 +1,63 @@ +/* GtkMenuComponentPeer.java -- Implements MenuComponentPeer with GTK+ + Copyright (C) 1999 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.peer.MenuComponentPeer; + +public class GtkMenuComponentPeer extends GtkGenericPeer + implements MenuComponentPeer +{ + void create () + { + throw new RuntimeException (); + } + + void setFont () + { + } + + public GtkMenuComponentPeer (Object awtWidget) + { + super (awtWidget); + create (); + setFont (); + } + + public native void dispose(); +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java new file mode 100644 index 0000000..5728f26 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java @@ -0,0 +1,120 @@ +/* GtkMenuItemPeer.java -- Implements MenuItemPeer with GTK+ + Copyright (C) 1999, 2005 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.Font; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuComponent; +import java.awt.MenuItem; +import java.awt.peer.MenuItemPeer; +import java.awt.peer.MenuPeer; + +public class GtkMenuItemPeer extends GtkMenuComponentPeer + implements MenuItemPeer +{ + native void create (String label); + native void connectSignals (); + native void gtkWidgetModifyFont (String name, int style, int size); + + void create () + { + create (((MenuItem) awtWidget).getLabel()); + } + + public GtkMenuItemPeer (MenuItem item) + { + super (item); + setEnabled (item.isEnabled ()); + setParent (item); + + if (item.getParent() instanceof Menu && ! (item instanceof Menu)) + connectSignals(); + } + + void setFont () + { + MenuComponent mc = ((MenuComponent) awtWidget); + Font f = mc.getFont (); + + if (f == null) + { + MenuComponent parent = (MenuComponent) mc.getParent (); + Font pf = parent.getFont (); + gtkWidgetModifyFont (pf.getName (), pf.getStyle (), pf.getSize ()); + } + else + gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize()); + } + + void setParent (MenuItem item) + { + // add ourself differently, based on what type of parent we have + // yes, the typecasting here is nasty. + Object parent = item.getParent (); + if (parent instanceof MenuBar) + { + ((GtkMenuBarPeer)((MenuBar)parent).getPeer ()).addMenu ((MenuPeer) this); + } + else // parent instanceof Menu + { + ((GtkMenuPeer)((Menu)parent).getPeer ()).addItem (this, + item.getShortcut ()); + } + } + + public void disable () + { + setEnabled (false); + } + + public void enable () + { + setEnabled (true); + } + + public native void setEnabled(boolean b); + + public native void setLabel(String label); + + protected void postMenuActionEvent () + { + postActionEvent (((MenuItem)awtWidget).getActionCommand (), 0); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java new file mode 100644 index 0000000..80332dd --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java @@ -0,0 +1,103 @@ +/* GtkMenuPeer.java -- Implements MenuPeer with GTK+ + Copyright (C) 1999, 2005 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.Component; +import java.awt.Menu; +import java.awt.MenuContainer; +import java.awt.MenuItem; +import java.awt.MenuShortcut; +import java.awt.peer.MenuItemPeer; +import java.awt.peer.MenuPeer; + +public class GtkMenuPeer extends GtkMenuItemPeer + implements MenuPeer +{ + native void create (String label); + native void addItem (MenuItemPeer item, int key, boolean shiftModifier); + native void setupAccelGroup (GtkGenericPeer container); + native void addTearOff (); + + public GtkMenuPeer (Menu menu) + { + super (menu); + + if (menu.isTearOff()) + addTearOff(); + + MenuContainer parent = menu.getParent (); + if (parent instanceof Menu) + setupAccelGroup ((GtkGenericPeer)((Menu)parent).getPeer ()); + else if (parent instanceof Component) + setupAccelGroup ((GtkGenericPeer)((Component)parent).getPeer ()); + else + setupAccelGroup (null); + } + + public void addItem (MenuItem item) + { + int key = 0; + boolean shiftModifier = false; + + MenuShortcut ms = item.getShortcut (); + if (ms != null) + { + key = ms.getKey (); + shiftModifier = ms.usesShiftModifier (); + } + + addItem ((MenuItemPeer) item.getPeer (), key, shiftModifier); + } + + public void addItem (MenuItemPeer item, MenuShortcut ms) + { + int key = 0; + boolean shiftModifier = false; + + if (ms != null) + { + key = ms.getKey (); + shiftModifier = ms.usesShiftModifier (); + } + + addItem (item, key, shiftModifier); + } + + public native void delItem(int index); +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java new file mode 100644 index 0000000..fb5adde --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java @@ -0,0 +1,70 @@ +/* GtkPanelPeer.java -- Implements PanelPeer with GTK + Copyright (C) 1998, 1999 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.AWTEvent; +import java.awt.Panel; +import java.awt.event.MouseEvent; +import java.awt.peer.PanelPeer; + +public class GtkPanelPeer extends GtkContainerPeer + implements PanelPeer +{ + native void create (); + + public GtkPanelPeer (Panel p) + { + super (p); + } + + public void handleEvent (AWTEvent event) + { + int id = event.getID(); + + switch (id) + { + case MouseEvent.MOUSE_PRESSED: + awtComponent.requestFocusInWindow (); + break; + } + super.handleEvent (event); + } + + native void connectSignals (); +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java new file mode 100644 index 0000000..d14c16d --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java @@ -0,0 +1,74 @@ +/* GtkPopupMenuPeer.java -- Implements PopupMenuPeer with GTK+ + Copyright (C) 1999 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.Component; +import java.awt.Event; +import java.awt.MenuItem; +import java.awt.Point; +import java.awt.PopupMenu; +import java.awt.peer.PopupMenuPeer; + +public class GtkPopupMenuPeer extends GtkMenuPeer + implements PopupMenuPeer +{ + public GtkPopupMenuPeer (PopupMenu menu) + { + super (menu); + } + + native void setupAccelGroup (GtkGenericPeer container); + + void setParent (MenuItem item) + { + // we don't need to "add" ourselves to our parent + } + + native void show (int x, int y, long time); + public void show (Component origin, int x, int y) + { + Point abs = origin.getLocationOnScreen (); + show (abs.x + x, abs.y + y, 0); + } + + public void show (Event e) + { + + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java new file mode 100644 index 0000000..69f8b49 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java @@ -0,0 +1,113 @@ +/* GtkScrollPanePeer.java -- Implements ScrollPanePeer with GTK + Copyright (C) 1998, 1999, 2005 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.Adjustable; +import java.awt.Dimension; +import java.awt.ScrollPane; +import java.awt.peer.ScrollPanePeer; + +public class GtkScrollPanePeer extends GtkContainerPeer + implements ScrollPanePeer +{ + native void create (int width, int height); + + void create () + { + create (awtComponent.getWidth (), awtComponent.getHeight ()); + } + + // native void gtkScrolledWindowSetScrollPosition(int x, int y); + native void gtkScrolledWindowSetHScrollIncrement (int u); + native void gtkScrolledWindowSetVScrollIncrement (int u); + + public GtkScrollPanePeer (ScrollPane sp) + { + super (sp); + + setPolicy (sp.getScrollbarDisplayPolicy ()); + } + + native void setPolicy (int policy); + public void childResized (int width, int height) + { + int dim[] = new int[2]; + + gtkWidgetGetDimensions (dim); + + // If the child is in this range, GTK adds both scrollbars, but + // the AWT doesn't. So set the peer's scroll policy to + // GTK_POLICY_NEVER. + if ((width > dim[0] - getVScrollbarWidth () + && width <= dim[0]) + && (height > dim[1] - getHScrollbarHeight () + && height <= dim[1])) + setPolicy (ScrollPane.SCROLLBARS_NEVER); + else + setPolicy (((ScrollPane) awtComponent).getScrollbarDisplayPolicy ()); + } + + public native int getHScrollbarHeight(); + public native int getVScrollbarWidth(); + public native void setScrollPosition(int x, int y); + + public Dimension getPreferredSize () + { + return awtComponent.getSize(); + } + + public void setUnitIncrement (Adjustable adj, int u) + { + if (adj.getOrientation()==Adjustable.HORIZONTAL) + gtkScrolledWindowSetHScrollIncrement (u); + else + gtkScrolledWindowSetVScrollIncrement (u); + } + + public void setValue (Adjustable adj, int v) + { +// System.out.println("SPP: setVal: "+adj+":"+v); +// Point p=myScrollPane.getScrollPosition (); +// if (adj.getOrientation()==Adjustable.HORIZONTAL) +// gtkScrolledWindowSetScrollPosition (v,p.y); +// else +// gtkScrolledWindowSetScrollPosition (p.x,v); +// adj.setValue(v); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java new file mode 100644 index 0000000..aa3a26e --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java @@ -0,0 +1,80 @@ +/* GtkScrollbarPeer.java -- Implements ScrollbarPeer with GTK+ + Copyright (C) 1998, 1999, 2005 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.Adjustable; +import java.awt.Scrollbar; +import java.awt.event.AdjustmentEvent; +import java.awt.peer.ScrollbarPeer; + +public class GtkScrollbarPeer extends GtkComponentPeer + implements ScrollbarPeer +{ + void create () + { + Scrollbar sb = (Scrollbar) awtComponent; + + create (sb.getOrientation (), sb.getValue (), + sb.getMinimum (), sb.getMaximum (), + sb.getUnitIncrement (), sb.getBlockIncrement (), + sb.getVisibleAmount ()); + } + + native void create (int orientation, int value, + int min, int max, int stepIncr, int pageIncr, + int visibleAmount); + + native void connectSignals (); + + public GtkScrollbarPeer (Scrollbar s) + { + super (s); + } + + public native void setLineIncrement(int amount); + public native void setPageIncrement(int amount); + public native void setValues(int value, int visible, int min, int max); + + protected void postAdjustmentEvent (int type, int value) + { + q().postEvent (new AdjustmentEvent ((Adjustable)awtComponent, + AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, + type, value)); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java new file mode 100644 index 0000000..a842b83 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java @@ -0,0 +1,212 @@ +/* GtkTextAreaPeer.java -- Implements TextAreaPeer with GTK + Copyright (C) 1998, 1999, 2002 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.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Rectangle; +import java.awt.TextArea; +import java.awt.peer.TextAreaPeer; +import java.awt.peer.TextComponentPeer; + +public class GtkTextAreaPeer extends GtkComponentPeer + implements TextComponentPeer, TextAreaPeer +{ + private static transient int DEFAULT_ROWS = 10; + private static transient int DEFAULT_COLS = 80; + + native void create (int width, int height, int scrollbarVisibility); + + native void gtkWidgetModifyFont (String name, int style, int size); + native void gtkWidgetRequestFocus (); + + public native void connectSignals (); + + public native int getCaretPosition (); + public native void setCaretPosition (int pos); + public native int getSelectionStart (); + public native int getSelectionEnd (); + public native String getText (); + public native void select (int start, int end); + public native void setEditable (boolean state); + public native void setText (String text); + + public int getIndexAtPoint(int x, int y) + { + // FIXME + return 0; + } + + public Rectangle getCharacterBounds (int pos) + { + // FIXME + return null; + } + + public long filterEvents (long filter) + { + // FIXME + return filter; + } + + void create () + { + Font f = awtComponent.getFont (); + + // By default, Sun sets a TextArea's font when its peer is + // created. If f != null then the peer's font is set by + // GtkComponent.create. + if (f == null) + { + f = new Font ("Dialog", Font.PLAIN, 12); + awtComponent.setFont (f); + } + + FontMetrics fm = getFontMetrics (f); + + TextArea ta = ((TextArea) awtComponent); + int sizeRows = ta.getRows (); + int sizeCols = ta.getColumns (); + + sizeRows = sizeRows == 0 ? DEFAULT_ROWS : sizeRows; + sizeCols = sizeCols == 0 ? DEFAULT_COLS : sizeCols; + + int width = sizeCols * fm.getMaxAdvance (); + int height = sizeRows * (fm.getMaxDescent () + fm.getMaxAscent ()); + + create (width, height, ta.getScrollbarVisibility ()); + setEditable (ta.isEditable ()); + } + + public GtkTextAreaPeer (TextArea ta) + { + super (ta); + + setText (ta.getText ()); + setCaretPosition (0); + } + + public native void insert (String str, int pos); + public native void replaceRange (String str, int start, int end); + + public Dimension getMinimumSize (int rows, int cols) + { + return minimumSize (rows == 0 ? DEFAULT_ROWS : rows, + cols == 0 ? DEFAULT_COLS : cols); + } + + public Dimension getPreferredSize (int rows, int cols) + { + return preferredSize (rows == 0 ? DEFAULT_ROWS : rows, + cols == 0 ? DEFAULT_COLS : cols); + } + + native int getHScrollbarHeight (); + native int getVScrollbarWidth (); + + // Deprecated + public Dimension minimumSize (int rows, int cols) + { + TextArea ta = ((TextArea) awtComponent); + int height = 0; + int width = 0; + + if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH + || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY) + height = getHScrollbarHeight (); + + if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH + || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY) + width = getVScrollbarWidth (); + + Font f = awtComponent.getFont (); + if (f == null) + return new Dimension (width, height); + + FontMetrics fm = getFontMetrics (f); + + int sizeRows = rows == 0 ? DEFAULT_ROWS : rows; + int sizeCols = cols == 0 ? DEFAULT_COLS : cols; + + width += sizeCols * fm.getMaxAdvance (); + height += sizeRows * (fm.getMaxDescent () + fm.getMaxAscent ()); + + return new Dimension (width, height); + } + + public Dimension preferredSize (int rows, int cols) + { + TextArea ta = ((TextArea) awtComponent); + int height = 0; + int width = 0; + + if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH + || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY) + height = getHScrollbarHeight (); + + if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH + || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY) + width = getVScrollbarWidth (); + + Font f = awtComponent.getFont (); + if (f == null) + return new Dimension (width, height); + + FontMetrics fm = getFontMetrics (f); + + int sizeRows = rows == 0 ? DEFAULT_ROWS : rows; + int sizeCols = cols == 0 ? DEFAULT_COLS : cols; + + width += sizeCols * fm.getMaxAdvance (); + height += sizeRows * (fm.getMaxDescent () + fm.getMaxAscent ()); + + return new Dimension (width, height); + } + + public void replaceText (String str, int start, int end) + { + replaceRange (str, start, end); + } + + public void insertText (String str, int pos) + { + insert (str, pos); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java new file mode 100644 index 0000000..73a976b --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java @@ -0,0 +1,196 @@ +/* GtkTextFieldPeer.java -- Implements TextFieldPeer with GTK + Copyright (C) 1998, 1999, 2002 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.AWTEvent; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Rectangle; +import java.awt.TextField; +import java.awt.event.KeyEvent; +import java.awt.peer.TextFieldPeer; +import java.awt.peer.TextComponentPeer; + +public class GtkTextFieldPeer extends GtkComponentPeer + implements TextComponentPeer, TextFieldPeer +{ + native void create (int width); + native void gtkWidgetSetBackground (int red, int green, int blue); + native void gtkWidgetSetForeground (int red, int green, int blue); + + public native void connectSignals (); + + public native int getCaretPosition (); + public native void setCaretPosition (int pos); + public native int getSelectionStart (); + public native int getSelectionEnd (); + public native String getText (); + public native void select (int start, int end); + public native void setEditable (boolean state); + public native void setText (String text); + + public int getIndexAtPoint(int x, int y) + { + // FIXME + return 0; + } + + public Rectangle getCharacterBounds (int pos) + { + // FIXME + return null; + } + + public long filterEvents (long filter) + { + // FIXME + return filter; + } + + void create () + { + Font f = awtComponent.getFont (); + + // By default, Sun sets a TextField's font when its peer is + // created. If f != null then the peer's font is set by + // GtkComponent.create. + if (f == null) + { + f = new Font ("Dialog", Font.PLAIN, 12); + awtComponent.setFont (f); + } + + FontMetrics fm = getFontMetrics (f); + + TextField tf = ((TextField) awtComponent); + int cols = tf.getColumns (); + + int text_width = cols * fm.getMaxAdvance (); + + create (text_width); + + setEditable (tf.isEditable ()); + } + + native int gtkEntryGetBorderWidth (); + + native void gtkWidgetModifyFont (String name, int style, int size); + + public GtkTextFieldPeer (TextField tf) + { + super (tf); + + setText (tf.getText ()); + setCaretPosition (0); + + if (tf.echoCharIsSet ()) + setEchoChar (tf.getEchoChar ()); + } + + public Dimension getMinimumSize (int cols) + { + return minimumSize (cols); + } + + public Dimension getPreferredSize (int cols) + { + return preferredSize (cols); + } + + public native void setEchoChar (char c); + + // Deprecated + public Dimension minimumSize (int cols) + { + int dim[] = new int[2]; + + gtkWidgetGetPreferredDimensions (dim); + + Font f = awtComponent.getFont (); + if (f == null) + return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]); + + FontMetrics fm = getFontMetrics (f); + + int text_width = cols * fm.getMaxAdvance (); + + int width = text_width + 2 * gtkEntryGetBorderWidth (); + + return new Dimension (width, dim[1]); + } + + public Dimension preferredSize (int cols) + { + int dim[] = new int[2]; + + gtkWidgetGetPreferredDimensions (dim); + + Font f = awtComponent.getFont (); + if (f == null) + return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]); + + FontMetrics fm = getFontMetrics (f); + + int text_width = cols * fm.getMaxAdvance (); + + int width = text_width + 2 * gtkEntryGetBorderWidth (); + + return new Dimension (width, dim[1]); + } + + public void setEchoCharacter (char c) + { + setEchoChar (c); + } + + public void handleEvent (AWTEvent e) + { + if (e.getID () == KeyEvent.KEY_PRESSED) + { + KeyEvent ke = (KeyEvent) e; + + if (!ke.isConsumed () + && ke.getKeyCode () == KeyEvent.VK_ENTER) + postActionEvent (getText (), ke.getModifiersEx ()); + } + + super.handleEvent (e); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java new file mode 100644 index 0000000..6990110 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -0,0 +1,653 @@ +/* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers + Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005 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.classpath.Configuration; +import gnu.java.awt.EmbeddedWindow; +import gnu.java.awt.peer.ClasspathFontPeer; +import gnu.java.awt.peer.ClasspathTextLayoutPeer; +import gnu.java.awt.peer.EmbeddedWindowPeer; + +import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.peer.DragSourceContextPeer; +import java.awt.font.FontRenderContext; +import java.awt.im.InputMethodHighlight; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.peer.*; +import java.io.InputStream; +import java.net.URL; +import java.text.AttributedString; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; + +import javax.imageio.spi.IIORegistry; + +/* This class uses a deprecated method java.awt.peer.ComponentPeer.getPeer(). + This merits comment. We are basically calling Sun's bluff on this one. + We think Sun has deprecated it simply to discourage its use as it is + bad programming style. However, we need to get at a component's peer in + this class. If getPeer() ever goes away, we can implement a hash table + that will keep up with every window's peer, but for now this is faster. */ + +/** + * This class accesses a system property called + * <tt>gnu.java.awt.peer.gtk.Graphics</tt>. If the property is defined and + * equal to "Graphics2D", the cairo-based GdkGraphics2D will be used in + * drawing contexts. Any other value will cause the older GdkGraphics + * object to be used. + */ +public class GtkToolkit extends gnu.java.awt.ClasspathToolkit +{ + Hashtable containers = new Hashtable(); + static EventQueue q; + static Clipboard systemClipboard; + static boolean useGraphics2dSet; + static boolean useGraphics2d; + + public static boolean useGraphics2D() + { + if (useGraphics2dSet) + return useGraphics2d; + useGraphics2d = System.getProperty("gnu.java.awt.peer.gtk.Graphics", + "Graphics").equals("Graphics2D"); + useGraphics2dSet = true; + return useGraphics2d; + } + + static native void gtkInit(int portableNativeSync); + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + System.loadLibrary("gtkpeer"); + + int portableNativeSync; + String portNatSyncProp = + System.getProperty("gnu.classpath.awt.gtk.portable.native.sync"); + + if (portNatSyncProp == null) + portableNativeSync = -1; // unset + else if (Boolean.valueOf(portNatSyncProp).booleanValue()) + portableNativeSync = 1; // true + else + portableNativeSync = 0; // false + + gtkInit(portableNativeSync); + } + + public GtkToolkit () + { + systemClipboard = new GtkClipboard (); + } + + public native void beep(); + private native void getScreenSizeDimensions(int[] xy); + + public int checkImage (Image image, int width, int height, + ImageObserver observer) + { + int status = ImageObserver.ALLBITS + | ImageObserver.WIDTH + | ImageObserver.HEIGHT; + + if (image instanceof GtkImage) + return ((GtkImage) image).checkImage (observer); + + if (observer != null) + observer.imageUpdate (image, status, + -1, -1, + image.getWidth (observer), + image.getHeight (observer)); + + return status; + } + + /** + * A helper class to return to clients in cases where a BufferedImage is + * desired but its construction fails. + */ + private class GtkErrorImage extends Image + { + public GtkErrorImage() + { + } + + public int getWidth(ImageObserver observer) + { + return -1; + } + + public int getHeight(ImageObserver observer) + { + return -1; + } + + public ImageProducer getSource() + { + + return new ImageProducer() + { + HashSet consumers = new HashSet(); + public void addConsumer(ImageConsumer ic) + { + consumers.add(ic); + } + + public boolean isConsumer(ImageConsumer ic) + { + return consumers.contains(ic); + } + + public void removeConsumer(ImageConsumer ic) + { + consumers.remove(ic); + } + + public void startProduction(ImageConsumer ic) + { + consumers.add(ic); + Iterator i = consumers.iterator(); + while(i.hasNext()) + { + ImageConsumer c = (ImageConsumer) i.next(); + c.imageComplete(ImageConsumer.IMAGEERROR); + } + } + public void requestTopDownLeftRightResend(ImageConsumer ic) + { + startProduction(ic); + } + }; + } + + public Graphics getGraphics() + { + return null; + } + + public Object getProperty(String name, ImageObserver observer) + { + return null; + } + public Image getScaledInstance(int width, int height, int flags) + { + return new GtkErrorImage(); + } + + public void flush() + { + } + } + + + /** + * Helper to return either a BufferedImage -- the argument -- or a + * GtkErrorImage if the argument is null. + */ + + private Image bufferedImageOrError(BufferedImage b) + { + if (b == null) + return new GtkErrorImage(); + else + return b; + } + + + public Image createImage (String filename) + { + if (useGraphics2D()) + return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (filename)); + else + return new GtkImage (filename); + } + + public Image createImage (URL url) + { + if (useGraphics2D()) + return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (url)); + else + { + GdkPixbufDecoder d = new GdkPixbufDecoder (url); + GtkImage image = new GtkImage (d); + return image; + } + } + + public Image createImage (ImageProducer producer) + { + if (useGraphics2D()) + return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (producer)); + else + return new GtkImage (producer); + } + + public Image createImage (byte[] imagedata, int imageoffset, + int imagelength) + { + if (useGraphics2D()) + return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (imagedata, + imageoffset, + imagelength)); + else + { + GdkPixbufDecoder d = new GdkPixbufDecoder (imagedata, + imageoffset, + imagelength); + GtkImage image = new GtkImage (d); + return image; + } + } + + /** + * Creates an ImageProducer from the specified URL. The image is assumed + * to be in a recognised format. + * + * @param url URL to read image data from. + */ + public ImageProducer createImageProducer(URL url) + { + return new GdkPixbufDecoder(url); + } + + /** + * Returns the native color model (which isn't the same as the default + * ARGB color model, but doesn't have to be). + */ + public ColorModel getColorModel () + { + /* Return the GDK-native ABGR format */ + return new DirectColorModel(32, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000); + } + + public String[] getFontList () + { + return (new String[] { "Dialog", + "DialogInput", + "Monospaced", + "Serif", + "SansSerif" }); + } + + private class LRUCache extends LinkedHashMap + { + int max_entries; + public LRUCache(int max) + { + super(max, 0.75f, true); + max_entries = max; + } + protected boolean removeEldestEntry(Map.Entry eldest) + { + return size() > max_entries; + } + } + + private LRUCache fontCache = new LRUCache(50); + private LRUCache metricsCache = new LRUCache(50); + private LRUCache imageCache = new LRUCache(50); + + public FontMetrics getFontMetrics (Font font) + { + synchronized (metricsCache) + { + if (metricsCache.containsKey(font)) + return (FontMetrics) metricsCache.get(font); + } + + FontMetrics m = new GdkFontMetrics (font); + synchronized (metricsCache) + { + metricsCache.put(font, m); + } + return m; + } + + public Image getImage (String filename) + { + if (imageCache.containsKey(filename)) + return (Image) imageCache.get(filename); + else + { + Image im = createImage(filename); + imageCache.put(filename, im); + return im; + } + } + + public Image getImage (URL url) + { + if (imageCache.containsKey(url)) + return (Image) imageCache.get(url); + else + { + Image im = createImage(url); + imageCache.put(url, im); + return im; + } + } + + public PrintJob getPrintJob (Frame frame, String jobtitle, Properties props) + { + return null; + } + + public native int getScreenResolution(); + + public Dimension getScreenSize () + { + int dim[] = new int[2]; + getScreenSizeDimensions(dim); + return new Dimension(dim[0], dim[1]); + } + + public Clipboard getSystemClipboard() + { + return systemClipboard; + } + + /** + * Prepares a GtkImage. For every other kind of Image it just + * assumes the image is already prepared for rendering. + */ + public boolean prepareImage (Image image, int width, int height, + ImageObserver observer) + { + /* GtkImages are always prepared, as long as they're loaded. */ + if (image instanceof GtkImage) + return ((((GtkImage)image).checkImage (observer) & + ImageObserver.ALLBITS) != 0); + + /* Assume anything else is too */ + return true; + } + + public native void sync(); + + protected void setComponentState (Component c, GtkComponentPeer cp) + { + /* Make the Component reflect Peer defaults */ + if (c.getForeground () == null) + c.setForeground (cp.getForeground ()); + if (c.getBackground () == null) + c.setBackground (cp.getBackground ()); + // if (c.getFont () == null) + // c.setFont (cp.getFont ()); + + /* Make the Peer reflect the state of the Component */ + if (! (c instanceof Window)) + { + cp.setCursor (c.getCursor ()); + + Rectangle bounds = c.getBounds (); + cp.setBounds (bounds.x, bounds.y, bounds.width, bounds.height); + cp.setVisible (c.isVisible ()); + } + } + + protected ButtonPeer createButton (Button b) + { + return new GtkButtonPeer (b); + } + + protected CanvasPeer createCanvas (Canvas c) + { + return new GtkCanvasPeer (c); + } + + protected CheckboxPeer createCheckbox (Checkbox cb) + { + return new GtkCheckboxPeer (cb); + } + + protected CheckboxMenuItemPeer createCheckboxMenuItem (CheckboxMenuItem cmi) + { + return new GtkCheckboxMenuItemPeer (cmi); + } + + protected ChoicePeer createChoice (Choice c) + { + return new GtkChoicePeer (c); + } + + protected DialogPeer createDialog (Dialog d) + { + return new GtkDialogPeer (d); + } + + protected FileDialogPeer createFileDialog (FileDialog fd) + { + return new GtkFileDialogPeer (fd); + } + + protected FramePeer createFrame (Frame f) + { + return new GtkFramePeer (f); + } + + protected LabelPeer createLabel (Label label) + { + return new GtkLabelPeer (label); + } + + protected ListPeer createList (List list) + { + return new GtkListPeer (list); + } + + protected MenuPeer createMenu (Menu m) + { + return new GtkMenuPeer (m); + } + + protected MenuBarPeer createMenuBar (MenuBar mb) + { + return new GtkMenuBarPeer (mb); + } + + protected MenuItemPeer createMenuItem (MenuItem mi) + { + return new GtkMenuItemPeer (mi); + } + + protected PanelPeer createPanel (Panel p) + { + return new GtkPanelPeer (p); + } + + protected PopupMenuPeer createPopupMenu (PopupMenu target) + { + return new GtkPopupMenuPeer (target); + } + + protected ScrollPanePeer createScrollPane (ScrollPane sp) + { + return new GtkScrollPanePeer (sp); + } + + protected ScrollbarPeer createScrollbar (Scrollbar sb) + { + return new GtkScrollbarPeer (sb); + } + + protected TextAreaPeer createTextArea (TextArea ta) + { + return new GtkTextAreaPeer (ta); + } + + protected TextFieldPeer createTextField (TextField tf) + { + return new GtkTextFieldPeer (tf); + } + + protected WindowPeer createWindow (Window w) + { + return new GtkWindowPeer (w); + } + + public EmbeddedWindowPeer createEmbeddedWindow (EmbeddedWindow w) + { + return new GtkEmbeddedWindowPeer (w); + } + + /** + * @deprecated part of the older "logical font" system in earlier AWT + * implementations. Our newer Font class uses getClasspathFontPeer. + */ + protected FontPeer getFontPeer (String name, int style) { + // All fonts get a default size of 12 if size is not specified. + return getFontPeer(name, style, 12); + } + + /** + * Private method that allows size to be set at initialization time. + */ + private FontPeer getFontPeer (String name, int style, int size) + { + Map attrs = new HashMap (); + ClasspathFontPeer.copyStyleToAttrs (style, attrs); + ClasspathFontPeer.copySizeToAttrs (size, attrs); + return getClasspathFontPeer (name, attrs); + } + + /** + * Newer method to produce a peer for a Font object, even though Sun's + * design claims Font should now be peerless, we do not agree with this + * model, hence "ClasspathFontPeer". + */ + + public ClasspathFontPeer getClasspathFontPeer (String name, Map attrs) + { + Map keyMap = new HashMap (attrs); + // We don't know what kind of "name" the user requested (logical, face, + // family), and we don't actually *need* to know here. The worst case + // involves failure to consolidate fonts with the same backend in our + // cache. This is harmless. + keyMap.put ("GtkToolkit.RequestedFontName", name); + if (fontCache.containsKey (keyMap)) + return (ClasspathFontPeer) fontCache.get (keyMap); + else + { + ClasspathFontPeer newPeer = new GdkFontPeer (name, attrs); + fontCache.put (keyMap, newPeer); + return newPeer; + } + } + + public ClasspathTextLayoutPeer getClasspathTextLayoutPeer (AttributedString str, + FontRenderContext frc) + { + return new GdkTextLayout(str, frc); + } + + protected EventQueue getSystemEventQueueImpl() + { + synchronized (GtkToolkit.class) + { + if (q == null) + { + q = new EventQueue(); + GtkGenericPeer.enableQueue (q); + } + } + return q; + } + + protected native void loadSystemColors (int[] systemColors); + + public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e) + { + throw new Error("not implemented"); + } + + public Map mapInputMethodHighlight(InputMethodHighlight highlight) + { + throw new Error("not implemented"); + } + + public Rectangle getBounds() + { + int[] dims = new int[2]; + getScreenSizeDimensions(dims); + return new Rectangle(0, 0, dims[0], dims[1]); + } + + // ClasspathToolkit methods + + public GraphicsEnvironment getLocalGraphicsEnvironment() + { + return new GdkGraphicsEnvironment(this); + } + + public Font createFont(int format, InputStream stream) + { + throw new UnsupportedOperationException(); + } + + public RobotPeer createRobot (GraphicsDevice screen) throws AWTException + { + return new GdkRobotPeer (screen); + } + + public void registerImageIOSpis(IIORegistry reg) + { + GdkPixbufDecoder.registerSpis(reg); + } + + public native boolean nativeQueueEmpty(); + public native void wakeNativeQueue(); + public native void iterateNativeQueue(EventQueue locked, boolean block); + +} // class GtkToolkit diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java new file mode 100644 index 0000000..496090a --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java @@ -0,0 +1,118 @@ +/* GtkVolatileImage.java -- a hardware-accelerated image buffer + Copyright (C) 2005 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.ImageCapabilities; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; +import java.awt.image.VolatileImage; + +public class GtkVolatileImage extends VolatileImage +{ + private int width; + private int height; + private ImageCapabilities caps; + + public GtkVolatileImage(int width, int height) + { + this(width, height, null); + } + + public GtkVolatileImage(int width, int height, ImageCapabilities caps) + { + this.width = width; + this.height = height; + this.caps = caps; + } + + // FIXME: should return a buffered image snapshot of the accelerated + // visual + public BufferedImage getSnapshot() + { + return null; + } + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + + // FIXME: should return a graphics wrapper around this image's + // visual + public Graphics2D createGraphics() + { + return null; + } + + public int validate(GraphicsConfiguration gc) + { + return VolatileImage.IMAGE_OK; + } + + public boolean contentsLost() + { + return false; + } + + public ImageCapabilities getCapabilities() + { + return caps; + } + + public synchronized Object getProperty (String name, ImageObserver observer) + { + return null; + } + + public synchronized int getWidth (ImageObserver observer) + { + return width; + } + + public synchronized int getHeight (ImageObserver observer) + { + return height; + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java new file mode 100644 index 0000000..71e05a8 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java @@ -0,0 +1,212 @@ +/* GtkWindowPeer.java -- Implements WindowPeer with GTK + Copyright (C) 1998, 1999, 2002, 2005 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.Component; +import java.awt.Frame; +import java.awt.Window; +import java.awt.event.WindowEvent; +import java.awt.peer.WindowPeer; + +public class GtkWindowPeer extends GtkContainerPeer + implements WindowPeer +{ + protected static final int GDK_WINDOW_TYPE_HINT_NORMAL = 0; + protected static final int GDK_WINDOW_TYPE_HINT_DIALOG = 1; + protected static final int GDK_WINDOW_TYPE_HINT_MENU = 2; + protected static final int GDK_WINDOW_TYPE_HINT_TOOLBAR = 3; + protected static final int GDK_WINDOW_TYPE_HINT_SPLASHSCREEN = 4; + protected static final int GDK_WINDOW_TYPE_HINT_UTILITY = 5; + protected static final int GDK_WINDOW_TYPE_HINT_DOCK = 6; + protected static final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7; + + private boolean hasBeenShown = false; + private int oldState = Frame.NORMAL; + + native void gtkWindowSetTitle (String title); + native void gtkWindowSetResizable (boolean resizable); + native void gtkWindowSetModal (boolean modal); + + native void realize (); + + int getWidth () + { + return awtComponent.getWidth(); + } + + int getHeight () + { + return awtComponent.getHeight(); + } + + native void create (int type, boolean decorated, GtkWindowPeer parent); + + void create (int type, boolean decorated) + { + GtkWindowPeer parent_peer = null; + Component parent = awtComponent.getParent(); + + if (parent != null) + parent_peer = (GtkWindowPeer) awtComponent.getParent().getPeer(); + + create (type, decorated, parent_peer); + } + + void create () + { + // Create a normal undecorated window. + create (GDK_WINDOW_TYPE_HINT_NORMAL, false); + } + + void setParent () + { + setVisible (awtComponent.isVisible ()); + setEnabled (awtComponent.isEnabled ()); + } + + void setVisibleAndEnabled () + { + } + + native void connectSignals (); + + public GtkWindowPeer (Window window) + { + super (window); + } + + public native void toBack(); + public native void toFront(); + + native void nativeSetBounds (int x, int y, int width, int height); + + public void setBounds (int x, int y, int width, int height) + { + nativeSetBounds (x, y, + width - insets.left - insets.right, + height - insets.top - insets.bottom); + } + + public void setTitle (String title) + { + gtkWindowSetTitle (title); + } + + native void setSize (int width, int height); + + public void setResizable (boolean resizable) + { + // Call setSize; otherwise when resizable is changed from true to + // false the window will shrink to the dimensions it had before it + // was resizable. + setSize (awtComponent.getWidth() - insets.left - insets.right, + awtComponent.getHeight() - insets.top - insets.bottom); + gtkWindowSetResizable (resizable); + } + + native void setBoundsCallback (Window window, + int x, int y, + int width, int height); + + protected void postInsetsChangedEvent (int top, int left, + int bottom, int right) + { + insets.top = top; + insets.left = left; + insets.bottom = bottom; + insets.right = right; + } + + protected void postConfigureEvent (int x, int y, int width, int height) + { + int frame_x = x - insets.left; + int frame_y = y - insets.top; + int frame_width = width + insets.left + insets.right; + int frame_height = height + insets.top + insets.bottom; + + if (frame_x != awtComponent.getX() + || frame_y != awtComponent.getY() + || frame_width != awtComponent.getWidth() + || frame_height != awtComponent.getHeight()) + { + setBoundsCallback ((Window) awtComponent, + frame_x, frame_y, frame_width, frame_height); + + awtComponent.validate(); + } + } + + native void nativeSetVisible (boolean b); + public void setVisible (boolean b) + { + // Prevent the window manager from automatically placing this + // window when it is shown. + if (b) + setBounds (awtComponent.getX(), + awtComponent.getY(), + awtComponent.getWidth(), + awtComponent.getHeight()); + nativeSetVisible (b); + } + + void postWindowEvent (int id, Window opposite, int newState) + { + if (id == WindowEvent.WINDOW_OPENED) + { + // Post a WINDOW_OPENED event the first time this window is shown. + if (!hasBeenShown) + { + q().postEvent (new WindowEvent ((Window) awtComponent, id, + opposite)); + hasBeenShown = true; + } + } + else if (id == WindowEvent.WINDOW_STATE_CHANGED) + { + if (oldState != newState) + { + q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite, + oldState, newState)); + oldState = newState; + } + } + else + q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite)); + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/package.html b/libjava/classpath/gnu/java/awt/peer/gtk/package.html new file mode 100644 index 0000000..8dd4dd8 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/gtk/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in gnu.java.awt.peer.gtk package. + Copyright (C) 2005 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. --> + +<html> +<head><title>GNU Classpath - gnu.java.awt.peer.gtk</title></head> + +<body> +<p>This package implements the GTK peer for java.awt.</p> + +</body> +</html> diff --git a/libjava/classpath/gnu/java/awt/peer/package.html b/libjava/classpath/gnu/java/awt/peer/package.html new file mode 100644 index 0000000..846759a --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in gnu.java.awt.peer package. + Copyright (C) 2005 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. --> + +<html> +<head><title>GNU Classpath - gnu.java.awt.peer</title></head> + +<body> +<p></p> + +</body> +</html> |