diff options
Diffstat (limited to 'libjava/gnu/java')
53 files changed, 3824 insertions, 889 deletions
diff --git a/libjava/gnu/java/awt/BitwiseXORComposite.java b/libjava/gnu/java/awt/BitwiseXORComposite.java index dd4f015b42a..6a05ee6c51b 100644 --- a/libjava/gnu/java/awt/BitwiseXORComposite.java +++ b/libjava/gnu/java/awt/BitwiseXORComposite.java @@ -1,5 +1,5 @@ /* BitwiseXORComposite.java -- Composite for emulating old-style XOR. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,7 +41,6 @@ package gnu.java.awt; import java.awt.Color; import java.awt.Composite; import java.awt.CompositeContext; -import java.awt.Graphics; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.image.ColorModel; diff --git a/libjava/gnu/java/awt/ClasspathToolkit.java b/libjava/gnu/java/awt/ClasspathToolkit.java index 92934593d39..c2492315b08 100644 --- a/libjava/gnu/java/awt/ClasspathToolkit.java +++ b/libjava/gnu/java/awt/ClasspathToolkit.java @@ -1,5 +1,5 @@ /* ClasspathToolkit.java -- Abstract superclass for Classpath toolkits. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,27 +38,27 @@ exception statement from your version. */ package gnu.java.awt; +import gnu.java.awt.peer.ClasspathFontPeer; +import gnu.java.awt.peer.ClasspathTextLayoutPeer; + import java.awt.Image; import java.awt.Dimension; import java.awt.DisplayMode; import java.awt.Font; -import java.awt.FontFormatException; import java.awt.FontMetrics; import java.awt.GraphicsEnvironment; -import java.awt.HeadlessException; import java.awt.Toolkit; +import java.awt.font.FontRenderContext; import java.awt.image.ColorModel; import java.awt.image.ImageProducer; import java.io.File; import java.io.InputStream; -import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.text.AttributedString; import java.util.HashMap; import java.util.Map; -import gnu.java.awt.peer.ClasspathFontPeer; - /** * An abstract superclass for Classpath toolkits. @@ -171,6 +171,9 @@ public abstract class ClasspathToolkit 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. diff --git a/libjava/gnu/java/awt/color/CieXyzConverter.java b/libjava/gnu/java/awt/color/CieXyzConverter.java new file mode 100644 index 00000000000..ee183cd64bb --- /dev/null +++ b/libjava/gnu/java/awt/color/CieXyzConverter.java @@ -0,0 +1,74 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/color/ClutProfileConverter.java b/libjava/gnu/java/awt/color/ClutProfileConverter.java new file mode 100644 index 00000000000..d33a6887eec --- /dev/null +++ b/libjava/gnu/java/awt/color/ClutProfileConverter.java @@ -0,0 +1,154 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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; + + +/** + * 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/gnu/java/awt/color/ColorLookUpTable.java b/libjava/gnu/java/awt/color/ColorLookUpTable.java new file mode 100644 index 00000000000..138d27adb35 --- /dev/null +++ b/libjava/gnu/java/awt/color/ColorLookUpTable.java @@ -0,0 +1,430 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/color/ColorSpaceConverter.java b/libjava/gnu/java/awt/color/ColorSpaceConverter.java new file mode 100644 index 00000000000..1fee749258e --- /dev/null +++ b/libjava/gnu/java/awt/color/ColorSpaceConverter.java @@ -0,0 +1,70 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/color/GrayProfileConverter.java b/libjava/gnu/java/awt/color/GrayProfileConverter.java new file mode 100644 index 00000000000..22dd49360b2 --- /dev/null +++ b/libjava/gnu/java/awt/color/GrayProfileConverter.java @@ -0,0 +1,138 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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.ProfileDataException; +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileGray; + + +/** + * 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/gnu/java/awt/color/GrayScaleConverter.java b/libjava/gnu/java/awt/color/GrayScaleConverter.java new file mode 100644 index 00000000000..446c3f6e56a --- /dev/null +++ b/libjava/gnu/java/awt/color/GrayScaleConverter.java @@ -0,0 +1,111 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/color/LinearRGBConverter.java b/libjava/gnu/java/awt/color/LinearRGBConverter.java new file mode 100644 index 00000000000..b40c2f02927 --- /dev/null +++ b/libjava/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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/color/ProfileHeader.java b/libjava/gnu/java/awt/color/ProfileHeader.java new file mode 100644 index 00000000000..fc4c0c3c912 --- /dev/null +++ b/libjava/gnu/java/awt/color/ProfileHeader.java @@ -0,0 +1,399 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/color/PyccConverter.java b/libjava/gnu/java/awt/color/PyccConverter.java new file mode 100644 index 00000000000..638d944a5b4 --- /dev/null +++ b/libjava/gnu/java/awt/color/PyccConverter.java @@ -0,0 +1,73 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/color/RgbProfileConverter.java b/libjava/gnu/java/awt/color/RgbProfileConverter.java new file mode 100644 index 00000000000..0482b3fe669 --- /dev/null +++ b/libjava/gnu/java/awt/color/RgbProfileConverter.java @@ -0,0 +1,245 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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.ProfileDataException; +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ProfileRGB; + + +/** + * 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/gnu/java/awt/color/SrgbConverter.java b/libjava/gnu/java/awt/color/SrgbConverter.java new file mode 100644 index 00000000000..65123e2305c --- /dev/null +++ b/libjava/gnu/java/awt/color/SrgbConverter.java @@ -0,0 +1,153 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/peer/gtk/GdkClasspathFontPeerMetrics.java b/libjava/gnu/java/awt/color/TagEntry.java index 2f019e4dbc4..7726e45d3ba 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkClasspathFontPeerMetrics.java +++ b/libjava/gnu/java/awt/color/TagEntry.java @@ -1,5 +1,5 @@ -/* GdkClasspathFontPeerMetrics.java - Copyright (C) 1999, 2002 Free Software Foundation, Inc. +/* 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. @@ -33,84 +33,90 @@ 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. */ + exception statement from your version. +*/ +package gnu.java.awt.color; -package gnu.java.awt.peer.gtk; -import java.awt.*; -import java.awt.font.*; -import java.awt.geom.*; - -public class GdkClasspathFontPeerMetrics extends FontMetrics +/** + * 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 { - private final int native_state = GtkGenericPeer.getUniqueInteger(); - - private static final int ASCENT = 0, MAX_ASCENT = 1, - DESCENT = 2, MAX_DESCENT = 3, - MAX_ADVANCE = 4; - - private int[] metrics; - private native int[] initState (Object font); - - public GdkClasspathFontPeerMetrics (Font font) + // 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) { - super (font); - metrics = initState (font.getPeer()); + this.signature = sig; + this.offset = offset; + this.size = size; + this.data = new byte[size]; + System.arraycopy(data, offset, this.data, 0, size); } - public int stringWidth (String str) + public TagEntry(int sig, byte[] data) { - GlyphVector gv = font.createGlyphVector - (new FontRenderContext - (new AffineTransform (), false, false), str); - Rectangle2D r = gv.getVisualBounds (); - return (int) r.getWidth (); + this.signature = sig; + this.size = data.length; + this.data = new byte[size]; + System.arraycopy(data, offset, this.data, 0, size); } - public int charWidth (char ch) + public byte[] getData() { - return stringWidth (new String (new char[] { ch })); + byte[] d = new byte[size]; + System.arraycopy(this.data, 0, d, 0, size); + return d; } - public int charsWidth (char data[], int off, int len) + public String hashKey() { - return stringWidth (new String (data, off, len)); + return tagHashKey(signature); } - /* - 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 () + public String toString() { - return 1; -// return metrics[ASCENT] + metrics[DESCENT]; + 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 getAscent () + public int getSignature() { - return metrics[ASCENT]; + return signature; } - public int getMaxAscent () + public int getSize() { - return metrics[MAX_ASCENT]; + return size; } - public int getDescent () + public int getOffset() { - return metrics[DESCENT]; + return offset; } - public int getMaxDescent () + public void setOffset(int offset) { - return metrics[MAX_DESCENT]; + this.offset = offset; } - public int getMaxAdvance () + public static String tagHashKey(int sig) { - return metrics[MAX_ADVANCE]; + return "" + sig; } } diff --git a/libjava/gnu/java/awt/color/ToneReproductionCurve.java b/libjava/gnu/java/awt/color/ToneReproductionCurve.java new file mode 100644 index 00000000000..a29598c4b48 --- /dev/null +++ b/libjava/gnu/java/awt/color/ToneReproductionCurve.java @@ -0,0 +1,178 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 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/gnu/java/awt/image/XBMDecoder.java b/libjava/gnu/java/awt/image/XBMDecoder.java index b80fd55de54..da58dbbcfe3 100644 --- a/libjava/gnu/java/awt/image/XBMDecoder.java +++ b/libjava/gnu/java/awt/image/XBMDecoder.java @@ -1,5 +1,5 @@ /* XBMDecoder -- Decodes X-bitmaps - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,13 +35,19 @@ 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.*; -import java.awt.image.*; -import java.util.*; -import java.io.*; +import java.awt.image.ColorModel; +import java.awt.image.ImageConsumer; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; import java.net.URL; +import java.util.StringTokenizer; +import java.util.Vector; public class XBMDecoder extends ImageDecoder { diff --git a/libjava/gnu/java/awt/peer/ClasspathFontPeer.java b/libjava/gnu/java/awt/peer/ClasspathFontPeer.java index 6b753aa15ec..79b1adf1807 100644 --- a/libjava/gnu/java/awt/peer/ClasspathFontPeer.java +++ b/libjava/gnu/java/awt/peer/ClasspathFontPeer.java @@ -160,7 +160,7 @@ public abstract class ClasspathFontPeer return name; } - protected static void copyStyleToAttrs (int style, Map attrs) + public static void copyStyleToAttrs (int style, Map attrs) { if ((style & Font.BOLD) == Font.BOLD) attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); @@ -179,7 +179,7 @@ public abstract class ClasspathFontPeer attrs.put (TextAttribute.FAMILY, fam); } - protected static void copySizeToAttrs (float size, Map attrs) + public static void copySizeToAttrs (float size, Map attrs) { attrs.put (TextAttribute.SIZE, new Float (size)); } @@ -218,7 +218,7 @@ public abstract class ClasspathFontPeer AffineTransform trans = this.transform; float size = this.size; int style = this.style; - + if (attribs.containsKey (TextAttribute.FAMILY)) family = (String) attribs.get (TextAttribute.FAMILY); @@ -243,7 +243,13 @@ public abstract class ClasspathFontPeer { 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)) { diff --git a/libjava/gnu/java/awt/peer/ClasspathTextLayoutPeer.java b/libjava/gnu/java/awt/peer/ClasspathTextLayoutPeer.java new file mode 100644 index 00000000000..143412caf99 --- /dev/null +++ b/libjava/gnu/java/awt/peer/ClasspathTextLayoutPeer.java @@ -0,0 +1,111 @@ +/* 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 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.Font; +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; +import java.text.CharacterIterator; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.Map; +import java.awt.font.TextAttribute; + + +/** + * @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/gnu/java/awt/peer/GLightweightPeer.java b/libjava/gnu/java/awt/peer/GLightweightPeer.java index 643c40f2ad4..c3219d1ea24 100644 --- a/libjava/gnu/java/awt/peer/GLightweightPeer.java +++ b/libjava/gnu/java/awt/peer/GLightweightPeer.java @@ -35,6 +35,7 @@ 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; diff --git a/libjava/gnu/java/awt/peer/gtk/GdkFontMetrics.java b/libjava/gnu/java/awt/peer/gtk/GdkFontMetrics.java index c7a73a3f362..3cd2f9a1cd2 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkFontMetrics.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkFontMetrics.java @@ -1,5 +1,5 @@ /* GdkFontMetrics.java - Copyright (C) 1999, 2002 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,33 +38,63 @@ 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 final int native_state = GtkGenericPeer.getUniqueInteger(); - - private static final int ASCENT = 0, MAX_ASCENT = 1, - DESCENT = 2, MAX_DESCENT = 3, - MAX_ADVANCE = 4; - - private int[] metrics; - private native int[] initState (String fname, int style, int size); + + 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; + + static native void getPeerFontMetrics(GdkFontPeer peer, double [] metrics); + static native void getPeerTextMetrics(GdkFontPeer peer, String str, double [] metrics); public GdkFontMetrics (Font font) - { - super (font); - metrics = initState (font.getName (), font.getStyle (), font.getSize ()); + { + 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]; + + if (GtkToolkit.useGraphics2D ()) + GdkGraphics2D.getPeerFontMetrics(peer, hires); + else + getPeerFontMetrics (peer, hires); + + for (int i = 0; i < 5; ++i) + font_metrics[i] = (int) hires[i]; } - - native public int stringWidth (String fname, int style, int size, - String str); - + public int stringWidth (String str) { - return stringWidth (font.getName (), font.getStyle (), font.getSize (), - str); + double [] hires = new double[6]; + if (GtkToolkit.useGraphics2D()) + GdkGraphics2D.getPeerTextMetrics(peer, str, hires); + else + getPeerTextMetrics(peer, str, hires); + return (int) hires [TEXT_METRICS_WIDTH]; } public int charWidth (char ch) @@ -77,34 +107,39 @@ public class GdkFontMetrics extends FontMetrics return stringWidth (new String (data, off, len)); } - // Sun's Motif implementation always returns 0 or 1 here (???). + /* + 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 0; + return 1; +// return metrics[ASCENT] + metrics[DESCENT]; } public int getAscent () { - return metrics[ASCENT]; + return font_metrics[FONT_METRICS_ASCENT]; } public int getMaxAscent () { - return metrics[MAX_ASCENT]; + return font_metrics[FONT_METRICS_MAX_ASCENT]; } public int getDescent () { - return metrics[DESCENT]; + return font_metrics[FONT_METRICS_DESCENT]; } public int getMaxDescent () { - return metrics[MAX_DESCENT]; + return font_metrics[FONT_METRICS_MAX_DESCENT]; } public int getMaxAdvance () { - return metrics[MAX_ADVANCE]; + return font_metrics[FONT_METRICS_MAX_ADVANCE]; } } diff --git a/libjava/gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java b/libjava/gnu/java/awt/peer/gtk/GdkFontPeer.java index 1cf24a98d61..ee051451026 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkFontPeer.java @@ -1,68 +1,62 @@ -/* GdkClasspathFontPeer.java -- backend implementation for Font object - 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., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 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. */ +/* GdkFontPeer.java -- Implements FontPeer with GTK+ + 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 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.FontPeer; import java.awt.*; -import java.awt.font.*; import java.awt.geom.*; -import java.io.InputStream; -import java.io.IOException; -import java.io.Serializable; +import java.awt.font.*; import java.util.Locale; import java.util.Map; -import java.util.StringTokenizer; +import java.util.ResourceBundle; +import java.util.MissingResourceException; import java.text.CharacterIterator; import java.text.AttributedCharacterIterator; import java.text.StringCharacterIterator; -import java.awt.font.TextAttribute; import gnu.classpath.Configuration; import gnu.java.awt.peer.ClasspathFontPeer; -/** - * This class represents a windowing system font using the Pango - * unicode/glyph/font library and the Cairo rendering library. - * - * @author Graydon Hoare (graydon@redhat.com) - */ - -public class GdkClasspathFontPeer extends ClasspathFontPeer +public class GdkFontPeer extends ClasspathFontPeer { + + native static void initStaticState (); + private final int native_state = GtkGenericPeer.getUniqueInteger (); + private static ResourceBundle bundle; static { @@ -71,26 +65,26 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer System.loadLibrary("gtkpeer"); } - if (GtkToolkit.useGraphics2D ()) - initStaticState (); - } - native static void initStaticState (); - private final int native_state = GtkGenericPeer.getUniqueInteger (); - + initStaticState (); - /* Instance Variables */ + 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); - - protected void sync () - { - this.setFont (this.familyName, this.style, (int)this.size); - } + private native void setFont (String family, int style, int size, boolean useGraphics2D); protected void finalize () { + if (GtkToolkit.useGraphics2D ()) + GdkGraphics2D.releasePeerGraphicsResource(this); dispose (); } @@ -101,49 +95,57 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer * triplicate. */ - private String buildString(CharacterIterator i) { - String s = new String (); - for(char c = i.first(); c != CharacterIterator.DONE; c = i.next()) - s += c; - return s; + 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) { - String s = new String (); + 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) - s += c; + sb.append(c); if (limit <= i) break; } - return s; + return sb.toString(); } - private String buildString(char[] chars, int begin, int limit) { - String s = new String (); - for(int i = begin; i <= limit; i++) - s += chars[i]; - return s; + private String buildString(char[] chars, int begin, int limit) + { + return new String(chars, begin, limit - begin); } /* Public API */ - public GdkClasspathFontPeer (String name, int style, int size) + 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); + setFont (this.familyName, this.style, (int)this.size, + GtkToolkit.useGraphics2D()); } - public GdkClasspathFontPeer (String name, Map attributes) + public GdkFontPeer (String name, Map attributes) { super(name, attributes); initState (); - setFont (this.familyName, this.style, (int)this.size); + setFont (this.familyName, this.style, (int)this.size, + GtkToolkit.useGraphics2D()); } - + public String getSubFamilyName(Font font, Locale locale) { return null; @@ -228,7 +230,6 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer } - public LineMetrics getLineMetrics (Font font, CharacterIterator ci, int begin, int limit, FontRenderContext rc) { @@ -288,8 +289,7 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer public FontMetrics getFontMetrics (Font font) { - return new GdkClasspathFontPeerMetrics (font); + return new GdkFontMetrics (font); } } - diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGlyphVector.java b/libjava/gnu/java/awt/peer/gtk/GdkGlyphVector.java index ff6b4cd291a..c37de5274ac 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkGlyphVector.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkGlyphVector.java @@ -1,57 +1,57 @@ /* GdkGlyphVector.java -- Glyph vector object - 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., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 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. */ + 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 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.*; -import java.awt.font.*; -import java.awt.geom.*; -import java.io.InputStream; -import java.io.IOException; -import java.io.Serializable; -import java.util.Locale; -import java.util.Map; -import java.util.StringTokenizer; -import java.text.CharacterIterator; -import java.text.AttributedCharacterIterator; import gnu.classpath.Configuration; -public class GdkGlyphVector extends GlyphVector +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +import java.awt.font.GlyphJustificationInfo; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +public class GdkGlyphVector extends GlyphVector { static @@ -70,7 +70,7 @@ public class GdkGlyphVector extends GlyphVector private Font font; private FontRenderContext ctx; - private native void initState (GdkClasspathFontPeer peer, FontRenderContext ctx); + private native void initState (GdkFontPeer peer, FontRenderContext ctx); private native void setChars (String s); private native void setGlyphCodes (int codes[]); private native void dispose (); @@ -109,7 +109,7 @@ public class GdkGlyphVector extends GlyphVector */ - public GdkGlyphVector (Font f, GdkClasspathFontPeer peer, FontRenderContext c, String s) + public GdkGlyphVector (Font f, GdkFontPeer peer, FontRenderContext c, String s) { font = f; ctx = c; @@ -117,7 +117,7 @@ public class GdkGlyphVector extends GlyphVector setChars (s); } - public GdkGlyphVector (Font f, GdkClasspathFontPeer peer, FontRenderContext c, int codes[]) + public GdkGlyphVector (Font f, GdkFontPeer peer, FontRenderContext c, int codes[]) { font = f; ctx = c; diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java b/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java index c374ba21826..5aacf5296c6 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkGraphics.java @@ -90,17 +90,31 @@ public class GdkGraphics extends Graphics GdkGraphics (GtkComponentPeer component) { this.component = component; + font = component.awtComponent.getFont (); + + if (component.isRealized ()) + initComponentGraphics (); + else + connectSignals (component); + } + + void initComponentGraphics () + { initState (component); color = component.awtComponent.getForeground (); - font = component.awtComponent.getFont (); 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); } @@ -113,16 +127,6 @@ public class GdkGraphics extends Graphics return new GdkGraphics (this); } -// public Graphics create (int x, int y, int width, int height) -// { -// GdkGraphics g = new GdkGraphics (this); -// System.out.println ("translating by: " + x +" " + y); -// g.translate (x, y); -// g.clipRect (0, 0, width, height); - -// return g; -// } - native public void dispose (); native void copyPixmap (Graphics g, int x, int y, int width, int height); @@ -134,24 +138,45 @@ public class GdkGraphics extends Graphics public boolean drawImage (Image img, int x, int y, Color bgcolor, ImageObserver observer) { + if (component != null && ! component.isRealized ()) + return false; + if (img instanceof GtkOffScreenImage) { + int width = img.getWidth (null); + int height = img.getHeight (null); copyPixmap (img.getGraphics (), - x, y, img.getWidth (null), img.getHeight (null)); + x, y, width, height); + // FIXME: need to differentiate between SOMEBITS and FRAMEBITS. + if (observer != null) + observer.imageUpdate (img, + ImageObserver.FRAMEBITS, + x, y, width, height); return true; } GtkImage image = (GtkImage) img; - new GtkImagePainter (image, this, x, y, -1, -1, bgcolor); + new GtkImagePainter (image, this, x, y, -1, -1, bgcolor, observer); return image.isLoaded (); } public boolean drawImage (Image img, int x, int y, ImageObserver observer) { + if (component != null && ! component.isRealized ()) + return false; + if (img instanceof GtkOffScreenImage) { + int width = img.getWidth (null); + int height = img.getHeight (null); copyPixmap (img.getGraphics (), - x, y, img.getWidth (null), img.getHeight (null)); + x, y, width, height); + + // FIXME: need to differentiate between SOMEBITS and FRAMEBITS. + if (observer != null) + observer.imageUpdate (img, + ImageObserver.FRAMEBITS, + x, y, width, height); return true; } @@ -164,22 +189,33 @@ public class GdkGraphics extends Graphics public boolean drawImage (Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { + if (component != null && ! component.isRealized ()) + return false; + if (img instanceof GtkOffScreenImage) { copyAndScalePixmap (img.getGraphics (), false, false, 0, 0, img.getWidth (null), img.getHeight (null), x, y, width, height); + // FIXME: need to differentiate between SOMEBITS and FRAMEBITS. + if (observer != null) + observer.imageUpdate (img, + ImageObserver.FRAMEBITS, + x, y, width, height); return true; } GtkImage image = (GtkImage) img; - new GtkImagePainter (image, this, x, y, width, height, bgcolor); + new GtkImagePainter (image, this, x, y, width, height, bgcolor, observer); return image.isLoaded (); } public boolean drawImage (Image img, int x, int y, int width, int height, ImageObserver observer) { + if (component != null && ! component.isRealized ()) + return false; + if (component != null) return drawImage (img, x, y, width, height, component.getBackground (), observer); @@ -192,6 +228,9 @@ public class GdkGraphics extends Graphics int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { + if (component != null && ! component.isRealized ()) + return false; + if (img instanceof GtkOffScreenImage) { int dx_start, dy_start, d_width, d_height; @@ -247,12 +286,18 @@ public class GdkGraphics extends Graphics copyAndScalePixmap (img.getGraphics (), x_flip, y_flip, sx_start, sy_start, s_width, s_height, dx_start, dy_start, d_width, d_height); + + // FIXME: need to differentiate between SOMEBITS and FRAMEBITS. + if (observer != null) + observer.imageUpdate (img, + ImageObserver.FRAMEBITS, + dx_start, dy_start, d_width, d_height); return true; } GtkImage image = (GtkImage) img; new GtkImagePainter (image, this, dx1, dy1, dx2, dy2, - sx1, sy1, sx2, sy2, bgcolor); + sx1, sy1, sx2, sy2, bgcolor, observer); return image.isLoaded (); } @@ -260,6 +305,9 @@ public class GdkGraphics extends Graphics int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { + if (component != null && ! component.isRealized ()) + return false; + if (component != null) return drawImage (img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, component.getBackground (), observer); @@ -285,11 +333,17 @@ public class GdkGraphics extends Graphics native public void drawRect(int x, int y, int width, int height); native public void fillRect (int x, int y, int width, int height); - native void drawString (String str, int x, int y, String fname, int style, int size); + 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 (str, x, y, font.getName(), font.getStyle(), font.getSize()); + drawString(getFontPeer(), str, x, y); } + public void drawString (AttributedCharacterIterator ci, int x, int y) { @@ -350,7 +404,6 @@ public class GdkGraphics extends Graphics public Rectangle getClipBounds () { -// System.out.println ("returning CLIP: " + clip); return new Rectangle (clip.x, clip.y, clip.width, clip.height); } @@ -373,6 +426,9 @@ public class GdkGraphics extends Graphics public void setClip (int x, int y, int width, int height) { + if (component != null && ! component.isRealized ()) + return; + clip.x = x; clip.y = y; clip.width = width; @@ -396,7 +452,7 @@ public class GdkGraphics extends Graphics public void setColor (Color c) { if (c == null) - color = new Color (0, 0, 0); + color = Color.BLACK; else color = c; @@ -407,7 +463,7 @@ public class GdkGraphics extends Graphics color.getGreen () ^ xorColor.getGreen (), color.getBlue () ^ xorColor.getBlue ()); } - + public void setFont (Font font) { this.font = font; @@ -437,6 +493,9 @@ public class GdkGraphics extends Graphics public void translate (int x, int y) { + if (component != null && ! component.isRealized ()) + return; + clip.x -= x; clip.y -= y; diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java index 0986960b8b3..82de03d5aec 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java @@ -1,5 +1,5 @@ /* GdkGraphics2D.java - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,21 +38,60 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.*; -import java.awt.geom.*; -import java.awt.font.*; -import java.awt.color.*; -import java.awt.image.*; -import java.awt.image.renderable.*; -import java.util.HashMap; -import java.util.Map; +import gnu.classpath.Configuration; +import gnu.java.awt.ClasspathToolkit; +import gnu.java.awt.peer.ClasspathFontPeer; +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.color.ColorSpace; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.GlyphJustificationInfo; +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.geom.AffineTransform; +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.FilteredImageSource; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; +import java.awt.image.ImagingOpException; +import java.awt.image.SampleModel; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; +import java.awt.image.WritableRaster; +import java.awt.image.renderable.RenderableImage; +import java.awt.image.renderable.RenderContext; import java.text.AttributedCharacterIterator; +import java.util.HashMap; +import java.util.Map; import java.util.Stack; -import java.lang.Integer; -import gnu.java.awt.ClasspathToolkit; -import gnu.java.awt.peer.ClasspathFontPeer; -import gnu.classpath.Configuration; public class GdkGraphics2D extends Graphics2D { @@ -85,6 +124,8 @@ public class GdkGraphics2D extends Graphics2D private RenderingHints hints; private BufferedImage bimage; + private Composite comp; + private Stack stateStack; native private void initState (GtkComponentPeer component); @@ -93,6 +134,7 @@ public class GdkGraphics2D extends Graphics2D native public void dispose (); native private int[] getImagePixels(); native private void cairoSurfaceSetFilter(int filter); + native void connectSignals (GtkComponentPeer component); public void finalize () { @@ -113,7 +155,7 @@ public class GdkGraphics2D extends Graphics2D { paint = g.paint; stroke = g.stroke; - hints = g.hints; + setRenderingHints (g.hints); if (g.fg.getAlpha() != -1) fg = new Color (g.fg.getRed (), g.fg.getGreen (), @@ -145,8 +187,8 @@ public class GdkGraphics2D extends Graphics2D setBackground (bg); setPaint (paint); setStroke (stroke); - setClip (clip); setTransform (transform); + setClip (clip); stateStack = new Stack(); } @@ -168,12 +210,22 @@ public class GdkGraphics2D extends Graphics2D GdkGraphics2D (GtkComponentPeer component) { this.component = component; + + setFont (new Font("SansSerif", Font.PLAIN, 12)); + + if (component.isRealized ()) + initComponentGraphics2D (); + else + connectSignals (component); + } + + void initComponentGraphics2D () + { initState (component); setColor (component.awtComponent.getForeground ()); setBackground (component.awtComponent.getBackground ()); setPaint (getColor()); - setFont (new Font("SansSerif", Font.PLAIN, 12)); setTransform (new AffineTransform ()); setStroke (new BasicStroke ()); setRenderingHints (getDefaultHints()); @@ -224,9 +276,6 @@ public class GdkGraphics2D extends Graphics2D private native void cairoSave (); private native void cairoRestore (); private native void cairoSetMatrix (double m[]); - private native void cairoSetFont (GdkClasspathFontPeer peer); - private native void cairoShowGlyphs (int codes[], - float positions[]); private native void cairoSetOperator (int cairoOperator); private native void cairoSetRGBColor (double red, double green, double blue); private native void cairoSetAlpha (double alpha); @@ -268,6 +317,7 @@ public class GdkGraphics2D extends Graphics2D private Shape clip; private AffineTransform transform; private Font font; + private Composite comp; DrawState (GdkGraphics2D g) { this.paint = g.paint; @@ -278,6 +328,7 @@ public class GdkGraphics2D extends Graphics2D if (g.transform != null) this.transform = (AffineTransform) g.transform.clone(); this.font = g.font; + this.comp = g.comp; } public void restore(GdkGraphics2D g) { @@ -288,6 +339,7 @@ public class GdkGraphics2D extends Graphics2D g.clip = this.clip; g.transform = this.transform; g.font = this.font; + g.comp = this.comp; } } @@ -303,17 +355,23 @@ public class GdkGraphics2D extends Graphics2D 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. - double x; - double y; - private void setPos (double nx, double ny) + private boolean shiftDrawCalls = false; + private final double shifted(double coord, boolean doShift) { - x = nx; - y = ny; + if (doShift) + return Math.floor(coord) + 0.5; + else + return coord; } - private void walkPath(PathIterator p) + private final void walkPath(PathIterator p, boolean doShift) { + double x = 0; + double y = 0; double coords[] = new double[6]; cairoSetFillRule (p.getWindingRule ()); @@ -324,13 +382,15 @@ public class GdkGraphics2D extends Graphics2D { case PathIterator.SEG_MOVETO: - setPos(coords[0], coords[1]); - cairoMoveTo (coords[0], coords[1]); + x = shifted(coords[0], doShift); + y = shifted(coords[1], doShift); + cairoMoveTo (x, y); break; case PathIterator.SEG_LINETO: - setPos(coords[0], coords[1]); - cairoLineTo (coords[0], coords[1]); + x = shifted(coords[0], doShift); + y = shifted(coords[1], doShift); + cairoLineTo (x, y); break; case PathIterator.SEG_QUADTO: @@ -338,23 +398,25 @@ public class GdkGraphics2D extends Graphics2D // splitting a quadratic bezier into a cubic: // see: http://pfaedit.sourceforge.net/bezier.html - double x1 = x + (2.0/3.0) * (coords[0] - x); - double y1 = y + (2.0/3.0) * (coords[1] - y); + 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) * (coords[2] - x); - double y2 = y1 + (1.0/3.0) * (coords[3] - 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); - setPos(coords[2], coords[3]); + x = shifted(coords[2], doShift); + y = shifted(coords[3], doShift); cairoCurveTo (x1, y1, x2, y2, - coords[2], coords[3]); + x, y); break; case PathIterator.SEG_CUBICTO: - setPos(coords[4], coords[5]); - cairoCurveTo (coords[0], coords[1], - coords[2], coords[3], - coords[4], coords[5]); + 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: @@ -365,7 +427,7 @@ public class GdkGraphics2D extends Graphics2D } - private Map getDefaultHints() + private final Map getDefaultHints() { HashMap defaultHints = new HashMap (); @@ -388,23 +450,19 @@ public class GdkGraphics2D extends Graphics2D } - private void updateBufferedImage() + private final void updateBufferedImage() { int[] pixels = getImagePixels(); updateImagePixels(pixels); } - private boolean isBufferedImageGraphics () + private final boolean isBufferedImageGraphics () { - - if (bimage != null) - return true; - else - return false; + return bimage != null; } - private void updateImagePixels (int[] pixels) + private final void updateImagePixels (int[] pixels) { // This function can only be used if @@ -439,11 +497,15 @@ public class GdkGraphics2D extends Graphics2D } - private boolean drawImage(Image img, - AffineTransform xform, - Color bgcolor, - ImageObserver obs) + private final boolean drawImage(Image img, + AffineTransform xform, + Color bgcolor, + ImageObserver obs) { + + if (img == null) + return false; + if (img instanceof GtkOffScreenImage && img.getGraphics () instanceof GdkGraphics2D && (xform == null @@ -461,8 +523,8 @@ public class GdkGraphics2D extends Graphics2D 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 @@ -475,23 +537,22 @@ public class GdkGraphics2D extends Graphics2D try { - invertedXform = xform.createInverse(); + 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.getData (), - invertedXform, - bgcolor); + BufferedImage b = (BufferedImage) img; + return drawRaster (b.getColorModel (), + b.getData (), + invertedXform, + bgcolor); } else { - // begin progressive loading in a separate thread - new PainterThread (this, img, invertedXform, bgcolor); - return false; + return this.drawImage(GdkPixbufDecoder.createBufferedImage(img.getSource()), + xform, bgcolor,obs); } } catch (NoninvertibleTransformException e) @@ -517,38 +578,25 @@ public class GdkGraphics2D extends Graphics2D return; } - stateSave (); cairoNewPath (); - - boolean normalize; - normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE) - || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT); - - if (normalize) - translate (0.5,0.5); if (s instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D)s; - cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); + cairoRectangle (shifted(r.getX (), shiftDrawCalls), + shifted(r.getY (), shiftDrawCalls), + r.getWidth (), r.getHeight ()); } else - walkPath (s.getPathIterator (null)); + walkPath (s.getPathIterator (null), shiftDrawCalls); cairoStroke (); - if (normalize) - translate (-0.5,-0.5); - - stateRestore (); - if (isBufferedImageGraphics ()) updateBufferedImage(); - } public void fill (Shape s) { - stateSave(); cairoNewPath (); if (s instanceof Rectangle2D) { @@ -556,9 +604,8 @@ public class GdkGraphics2D extends Graphics2D cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); } else - walkPath (s.getPathIterator (null)); + walkPath (s.getPathIterator (null), false); cairoFill (); - stateRestore (); if (isBufferedImageGraphics ()) updateBufferedImage(); @@ -592,8 +639,8 @@ public class GdkGraphics2D extends Graphics2D r.getWidth (), r.getHeight ()); } else - walkPath (clip.getPathIterator (null)); - cairoClosePath (); + walkPath (clip.getPathIterator (null), false); + // cairoClosePath (); cairoClip (); } } @@ -739,7 +786,7 @@ public class GdkGraphics2D extends Graphics2D { BasicStroke bs = (BasicStroke) stroke; cairoSetLineCap (bs.getEndCap()); - cairoSetLineWidth (bs.getLineWidth() / 2.0); + cairoSetLineWidth (bs.getLineWidth()); cairoSetLineJoin (bs.getLineJoin()); cairoSetMiterLimit (bs.getMiterLimit()); float dashes[] = bs.getDashArray(); @@ -771,6 +818,9 @@ public class GdkGraphics2D extends Graphics2D public void setColor (Color c) { + if (c == null) + c = Color.BLACK; + fg = c; paint = c; cairoSetRGBColor (fg.getRed() / 255.0, @@ -802,23 +852,23 @@ public class GdkGraphics2D extends Graphics2D 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 ()); - } - } + 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) { @@ -839,96 +889,34 @@ public class GdkGraphics2D extends Graphics2D r.getWidth (), r.getHeight ()); } else - walkPath (s.getPathIterator (null)); - cairoClosePath (); + 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) { - Color std = fg; - Color light = std.brighter(); - Color dark = std.darker(); - - if (!raised) - { - Color t = light; - light = dark; - dark = t; - } - - double x1 = (double) x; - double x2 = (double) x + width; - - double y1 = (double) y; - double y2 = (double) y + height; - - stateSave (); - - cairoNewPath (); - - boolean normalize; - normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE) - || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT); - - if (normalize) - { - x1 += 0.5; - y1 += 0.5; - x2 += 0.5; - y2 += 0.5; - } - - setColor (light); - cairoMoveTo (x1, y1); - cairoLineTo (x2, y1); - cairoLineTo (x2, y2); - cairoStroke (); - - cairoNewPath (); - setColor (dark); - cairoMoveTo (x1, y1); - cairoLineTo (x1, y2); - cairoLineTo (x2, y2); - cairoStroke (); - - stateRestore (); - + Stroke tmp = stroke; + setStroke(draw3DRectStroke); + super.draw3DRect(x, y, width, height, raised); + setStroke(tmp); if (isBufferedImageGraphics ()) updateBufferedImage(); - } public void fill3DRect(int x, int y, int width, int height, boolean raised) { - double step = 1.0; - if (stroke != null && stroke instanceof BasicStroke) - { - BasicStroke bs = (BasicStroke) stroke; - step = bs.getLineWidth(); - } - - Color bright = fg.brighter (); - Color dark = fg.darker (); - - draw3DRect (x, y, width, height, raised); - - stateSave (); - translate (step/2.0, step/2.0); - cairoNewPath (); - cairoRectangle ((double) x, (double) y, - ((double) width) - step, - ((double) height) - step ); - cairoClosePath (); - cairoFill (); - stateRestore (); - + Stroke tmp = stroke; + setStroke(draw3DRectStroke); + super.fill3DRect(x, y, width, height, raised); + setStroke(tmp); if (isBufferedImageGraphics ()) updateBufferedImage(); - } @@ -939,21 +927,21 @@ public class GdkGraphics2D extends Graphics2D public void fillRect (int x, int y, int width, int height) { - fill(new Rectangle (x, y, width, height)); + cairoNewPath (); + cairoRectangle (x, y, width, height); + cairoFill (); } public void clearRect (int x, int y, int width, int height) { - stateSave (); cairoSetRGBColor (bg.getRed() / 255.0, bg.getGreen() / 255.0, bg.getBlue() / 255.0); cairoSetAlpha (1.0); cairoNewPath (); cairoRectangle (x, y, width, height); - cairoClosePath (); cairoFill (); - stateRestore (); + setColor (fg); if (isBufferedImageGraphics ()) updateBufferedImage(); @@ -970,8 +958,8 @@ public class GdkGraphics2D extends Graphics2D return bg; } - private void doPolygon(int[] xPoints, int[] yPoints, int nPoints, - boolean close, boolean fill) + private final void doPolygon(int[] xPoints, int[] yPoints, int nPoints, + boolean close, boolean fill) { if (nPoints < 1) return; @@ -1026,9 +1014,9 @@ public class GdkGraphics2D extends Graphics2D doPolygon (xPoints, yPoints, nPoints, false, false); } - private boolean drawRaster (ColorModel cm, Raster r, - AffineTransform imageToUser, - Color bgcolor) + private final boolean drawRaster (ColorModel cm, Raster r, + AffineTransform imageToUser, + Color bgcolor) { if (r == null) return false; @@ -1087,10 +1075,7 @@ public class GdkGraphics2D extends Graphics2D } } - stateSave (); - translate (x, y); drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth (), i2u); - stateRestore (); if (isBufferedImageGraphics ()) updateBufferedImage(); @@ -1133,113 +1118,6 @@ public class GdkGraphics2D extends Graphics2D } - //////////////////////////////////////// - ////// Supporting Private Classes ////// - //////////////////////////////////////// - - private class PainterThread implements Runnable, ImageConsumer - { - - // this is a helper which is spun off when someone tries to do - // Graphics2D.drawImage on an image we cannot determine to be either - // one of our own offscreen images or a BufferedImage; that is, when - // someone wants to draw an image which is possibly still loading over - // a network or something. you run it in a separate thread and it - // writes through to the underlying Graphics2D as pixels becomg - // available. - - GdkGraphics2D gr; - Image image; - ColorModel defaultModel; - AffineTransform xform; - Color bgcolor; - - public PainterThread (GdkGraphics2D g, Image im, - AffineTransform xf, Color bg) - { - image = im; - xform = xf; - bgcolor = bg; - this.gr = (GdkGraphics2D) g.create (); - new Thread (this).start (); - } - - public void imageComplete (int status) - { - } - - public void setColorModel (ColorModel model) - { - defaultModel = model; - } - - public void setDimensions (int width, int height) - { - } - - public void setHints (int hintflags) - { - } - - public void setPixels (int x, int y, int w, int h, ColorModel model, - byte[] pixels, int off, int scansize) - { - } - - public void setPixels (int x, int y, int w, int h, ColorModel model, - int[] pixels, int off, int scansize) - { - gr.stateSave (); - gr.translate (x, y); - - if (model == null) - model = defaultModel; - - 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; - - // change all transparent pixels in the image to the - // specified bgcolor - - if (bgcolor != null) - { - for (int i = 0; i < pixels2.length; i++) - { - if (model.getAlpha (pixels2[i]) == 0) - pixels2[i] = bgcolor.getRGB (); - } - } - - double[] xf = new double[6]; - xform.getMatrix(xf); - gr.drawPixels (pixels2, w, h, scansize, xf); - gr.stateRestore (); - } - - public void setProperties (java.util.Hashtable props) - { - } - - public void run () - { - image.getSource ().startProduction (this); - gr.dispose (); - } - } - - - /////////////////////////////////////////////// ////// Unimplemented Stubs and Overloads ////// /////////////////////////////////////////////// @@ -1259,6 +1137,8 @@ public class GdkGraphics2D extends Graphics2D public void setComposite(Composite comp) { + this.comp = comp; + if (comp instanceof AlphaComposite) { AlphaComposite a = (AlphaComposite) comp; @@ -1297,8 +1177,11 @@ public class GdkGraphics2D extends Graphics2D 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) @@ -1331,6 +1214,9 @@ public class GdkGraphics2D extends Graphics2D 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) @@ -1345,7 +1231,10 @@ public class GdkGraphics2D extends Graphics2D public Composite getComposite() { - throw new java.lang.UnsupportedOperationException (); + if (comp == null) + return AlphaComposite.SrcOver; + else + return comp; } public FontRenderContext getFontRenderContext () @@ -1353,23 +1242,6 @@ public class GdkGraphics2D extends Graphics2D return new FontRenderContext (transform, true, true); } - public void drawGlyphVector (GlyphVector g, float x, float y) - { - stateSave (); - setFont (g.getFont ()); - translate ((double)x, (double)y); - cairoMoveTo (0, 0); - int nglyphs = g.getNumGlyphs (); - int codes[] = g.getGlyphCodes (0, nglyphs, (int []) null); - float posns[] = g.getGlyphPositions (0, nglyphs, (float []) null); - cairoShowGlyphs (codes, posns); - - if (isBufferedImageGraphics ()) - updateBufferedImage(); - - stateRestore (); - } - public void copyArea (int x, int y, int width, int height, int dx, int dy) { throw new java.lang.UnsupportedOperationException (); @@ -1418,6 +1290,9 @@ public class GdkGraphics2D extends Graphics2D Color bgcolor, ImageObserver observer) { + if (img == null) + return false; + Image subImage; int sourceWidth = sx2 - sx1; @@ -1501,15 +1376,40 @@ public class GdkGraphics2D extends Graphics2D drawLine (x1, y + height, x2, y + height); } - public void drawString (String str, int x, int y) + // these are the most accelerated painting paths + native void cairoDrawGdkGlyphVector (GdkFontPeer f, GdkGlyphVector gv, float x, float y); + native void cairoDrawGdkTextLayout (GdkFontPeer f, GdkTextLayout gl, float x, float y); + native void cairoDrawString (GdkFontPeer f, String str, float x, float y); + + GdkFontPeer getFontPeer() { - drawString (str, (float)x, (float)y); + return (GdkFontPeer) getFont().getPeer(); + } + + public void drawGdkGlyphVector(GdkGlyphVector gv, float x, float y) + { + cairoDrawGdkGlyphVector(getFontPeer(), gv, x, y); + if (isBufferedImageGraphics ()) + updateBufferedImage(); + } + + public void drawGdkTextLayout(GdkTextLayout gl, float x, float y) + { + cairoDrawGdkTextLayout(getFontPeer(), gl, x, y); + if (isBufferedImageGraphics ()) + updateBufferedImage(); } public void drawString (String str, float x, float y) { - GlyphVector gv = font.createGlyphVector (getFontRenderContext(), str); - drawGlyphVector (gv, x, y); + cairoDrawString(getFontPeer(), str, x, y); + if (isBufferedImageGraphics ()) + 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) @@ -1517,6 +1417,14 @@ public class GdkGraphics2D extends Graphics2D drawString (ci, (float)x, (float)y); } + public void drawGlyphVector (GlyphVector gv, float x, float y) + { + if (gv instanceof GdkGlyphVector) + drawGdkGlyphVector((GdkGlyphVector)gv, x, y); + else + throw new java.lang.UnsupportedOperationException (); + } + public void drawString (AttributedCharacterIterator ci, float x, float y) { GlyphVector gv = font.createGlyphVector (getFontRenderContext(), ci); @@ -1562,30 +1470,38 @@ public class GdkGraphics2D extends Graphics2D 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); + static native void getPeerTextMetrics (GdkFontPeer f, String str, double [] metrics); + static native void getPeerFontMetrics (GdkFontPeer f, double [] metrics); + public FontMetrics getFontMetrics () { + // 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 (font); } 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 GdkClasspathFontPeer) + if (f.getPeer() instanceof GdkFontPeer) font = f; else font = ((ClasspathToolkit)(Toolkit.getDefaultToolkit ())) - .getFont (f.getName(), f.getAttributes ()); - - if (f != null && - f.getPeer() instanceof GdkClasspathFontPeer) - cairoSetFont ((GdkClasspathFontPeer) f.getPeer()); + .getFont (f.getName(), f.getAttributes ()); } - + public String toString() { return getClass ().getName () + diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/libjava/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java index dbcd2d1c437..45e0c21c0f2 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java @@ -38,18 +38,20 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.*; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; +import java.awt.Shape; import java.awt.image.BufferedImage; import java.util.Locale; - public class GdkGraphicsEnvironment extends GraphicsEnvironment { - public GdkGraphicsEnvironment () { - super(); + super(); } public GraphicsDevice[] getScreenDevices () @@ -66,22 +68,28 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment { return new GdkGraphics2D (image); } + native private int nativeGetNumFontFamilies (); + native private void nativeGetFontFamilies (String[] family_names); public Font[] getAllFonts () { throw new java.lang.UnsupportedOperationException (); } - public String[] getAvailableFontFamilyNames () - { - 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 (); } - - -} // class GdkGraphicsEnvironment - +} diff --git a/libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java index 5c7fd96003b..a7b93e5b9ad 100644 --- a/libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java +++ b/libjava/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -1,52 +1,57 @@ /* GdkPixbufDecoder.java -- Image data decoding object - 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., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 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. */ + 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.image.*; +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.io.FileDescriptor; import java.io.FileInputStream; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URL; -import java.util.Vector; import java.util.Hashtable; -import gnu.classpath.Configuration; +import java.util.Vector; public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder { diff --git a/libjava/gnu/java/awt/peer/gtk/GdkTextLayout.java b/libjava/gnu/java/awt/peer/gtk/GdkTextLayout.java new file mode 100644 index 00000000000..26cfc16f0da --- /dev/null +++ b/libjava/gnu/java/awt/peer/gtk/GdkTextLayout.java @@ -0,0 +1,435 @@ +/* GdkTextLayout.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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 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.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +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.CharacterIterator; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.Map; +import java.awt.font.TextAttribute; + +import gnu.classpath.Configuration; +import gnu.java.awt.peer.ClasspathTextLayoutPeer; + +/** + * 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 (); + native static 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/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkButtonPeer.java index db8aed6087b..9fba828b74b 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkButtonPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkButtonPeer.java @@ -1,5 +1,5 @@ /* GtkButtonPeer.java -- Implements ButtonPeer with GTK - Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -43,8 +43,8 @@ import java.awt.Button; import java.awt.Component; import java.awt.Font; import java.awt.Point; -import java.awt.event.MouseEvent; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.awt.peer.ButtonPeer; public class GtkButtonPeer extends GtkComponentPeer @@ -52,13 +52,15 @@ public class GtkButtonPeer extends GtkComponentPeer { native void create (String label); - public native void connectJObject (); public native void connectSignals (); - native void gtkSetFont (String name, int style, int size); + 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) { @@ -86,8 +88,8 @@ public class GtkButtonPeer extends GtkComponentPeer if (!me.isConsumed () && (me.getModifiersEx () & MouseEvent.BUTTON1_DOWN_MASK) != 0 && awtComponent.getBounds().contains(p)) - postActionEvent (((Button)awtComponent).getActionCommand (), - me.getModifiersEx ()); + postActionEvent (((Button) awtComponent).getActionCommand (), + me.getModifiersEx ()); } if (e.getID () == KeyEvent.KEY_PRESSED) diff --git a/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java index 361136f08e9..a6fd1bac183 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java @@ -55,7 +55,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer public native void create (GtkCheckboxGroupPeer group); public native void nativeSetCheckboxGroup (GtkCheckboxGroupPeer group); public native void connectSignals (); - native void gtkSetFont (String name, int style, int size); + native void gtkWidgetModifyFont (String name, int style, int size); native void gtkButtonSetLabel (String label); native void gtkToggleButtonSetActive (boolean is_active); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkChoicePeer.java b/libjava/gnu/java/awt/peer/gtk/GtkChoicePeer.java index 2ecea5cb9ba..05464143dcf 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkChoicePeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkChoicePeer.java @@ -59,6 +59,10 @@ public class GtkChoicePeer extends GtkComponentPeer append (items); } + + int selected = c.getSelectedIndex(); + if (selected >= 0) + select(selected); } native void create (); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkClipboard.java b/libjava/gnu/java/awt/peer/gtk/GtkClipboard.java index 86678f8ab1c..ecc4c5cf7a1 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkClipboard.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkClipboard.java @@ -43,9 +43,9 @@ 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; -import java.io.IOException; public class GtkClipboard extends Clipboard { @@ -60,15 +60,13 @@ public class GtkClipboard extends Clipboard static boolean hasSelection = false; - protected - GtkClipboard () + protected GtkClipboard() { - super ("System Clipboard"); - initNativeState (); + super("System Clipboard"); + initNativeState(); } - public Transferable - getContents (Object requestor) + public Transferable getContents(Object requestor) { synchronized (this) { @@ -77,72 +75,76 @@ public class GtkClipboard extends Clipboard } /* Java doesn't own the selection, so we need to ask X11 */ + // XXX: Does this hold with Swing too ? synchronized (selectionLock) { - requestStringConversion (); + requestStringConversion(); + try { - selectionLock.wait (SELECTION_RECEIVED_TIMEOUT); + selectionLock.wait(SELECTION_RECEIVED_TIMEOUT); } catch (InterruptedException e) { return null; } - return (selection == null) ? null : new StringSelection (selection); + return selection == null ? null : new StringSelection(selection); } } - void - stringSelectionReceived (String newSelection) + void stringSelectionReceived(String newSelection) { synchronized (selectionLock) { selection = newSelection; - selectionLock.notify (); + selectionLock.notify(); } } /* convert Java clipboard data into a String suitable for sending to another application */ - synchronized String - stringSelectionHandler () throws IOException + 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; + 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"); + reader = new InputStreamReader + ((InputStream) + contents.getTransferData(DataFlavor.plainTextFlavor), "UNICODE"); - while (true) - { - numChars = reader.read (readBuf); - if (numChars == -1) - break; - sbuf.append (readBuf, 0, numChars); - } + while (true) + { + numChars = reader.read(readBuf); + if (numChars == -1) + break; + sbuf.append(readBuf, 0, numChars); + } - selection = new String (sbuf); - } - } catch (Exception e) { } + selection = new String(sbuf); + } + } + catch (Exception e) + { + } return selection; } - public synchronized void - setContents (Transferable contents, ClipboardOwner owner) + public synchronized void setContents(Transferable contents, + ClipboardOwner owner) { - selectionGet (); + selectionGet(); this.contents = contents; this.owner = owner; @@ -150,20 +152,19 @@ public class GtkClipboard extends Clipboard hasSelection = true; } - synchronized - void selectionClear () + synchronized void selectionClear() { hasSelection = false; if (owner != null) { - owner.lostOwnership (this, contents); + owner.lostOwnership(this, contents); owner = null; contents = null; } } - native void initNativeState (); - native static void requestStringConversion (); - native static void selectionGet (); + native void initNativeState(); + native static void requestStringConversion(); + native static void selectionGet(); } diff --git a/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java index eae5a948bc4..31d59ce19b0 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -77,6 +77,8 @@ public class GtkComponentPeer extends GtkGenericPeer 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 */ @@ -85,7 +87,6 @@ public class GtkComponentPeer extends GtkGenericPeer native int[] gtkWidgetGetForeground (); native int[] gtkWidgetGetBackground (); - native void gtkWidgetSetVisible (boolean b); native void gtkWidgetGetDimensions (int[] dim); native void gtkWidgetGetPreferredDimensions (int[] dim); native void gtkWidgetGetLocationOnScreen (int[] point); @@ -97,17 +98,14 @@ public class GtkComponentPeer extends GtkGenericPeer native void gtkWidgetRequestFocus (); native void gtkWidgetDispatchKeyEvent (int id, long when, int mods, int keyCode, int keyLocation); - native void gtkSetFont (String name, int style, int size); - native void gtkWidgetQueueDrawArea(int x, int y, int width, int height); - native void addExposeFilter(); - native void removeExposeFilter(); + + native boolean isRealized (); void create () { throw new RuntimeException (); } - native void connectJObject (); native void connectSignals (); protected GtkComponentPeer (Component awtComponent) @@ -118,9 +116,6 @@ public class GtkComponentPeer extends GtkGenericPeer create (); - setParent (); - - connectJObject (); connectSignals (); if (awtComponent.getForeground () != null) @@ -130,12 +125,22 @@ public class GtkComponentPeer extends GtkGenericPeer if (awtComponent.getFont() != null) setFont(awtComponent.getFont()); - setCursor (awtComponent.getCursor ()); + 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 (); + } + + void setParentAndBounds () + { + setParent (); setComponentBounds (); - Rectangle bounds = awtComponent.getBounds (); - setBounds (bounds.x, bounds.y, bounds.width, bounds.height); setVisibleAndEnabled (); } @@ -154,15 +159,32 @@ public class GtkComponentPeer extends GtkGenericPeer 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 so the default implementation does - * nothing. However some peers, like GtkFileDialogPeer, need to - * pass their size back to the AWT Component. + * 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 () @@ -180,7 +202,9 @@ public class GtkComponentPeer extends GtkGenericPeer public Image createImage (ImageProducer producer) { - return new GtkImage (producer, null); + GtkImage image = new GtkImage (producer, null); + producer.startProduction (image); + return image; } public Image createImage (int width, int height) @@ -195,6 +219,9 @@ public class GtkComponentPeer extends GtkGenericPeer else g = new GdkGraphics (width, height); + g.setColor(getBackground()); + g.fillRect(0, 0, width, height); + return new GtkOffScreenImage (null, g, width, height); } @@ -215,7 +242,7 @@ public class GtkComponentPeer extends GtkGenericPeer public FontMetrics getFontMetrics (Font font) { - return new GdkFontMetrics (font); + return getToolkit().getFontMetrics(font); } public Graphics getGraphics () @@ -265,8 +292,8 @@ public class GtkComponentPeer extends GtkGenericPeer // Some peers like GtkFileDialogPeer are repainted by Gtk itself if (g == null) break; - - g.setClip (((PaintEvent)event).getUpdateRect()); + + g.setClip (((PaintEvent) event).getUpdateRect()); if (id == PaintEvent.PAINT) awtComponent.paint (g); @@ -310,21 +337,6 @@ public class GtkComponentPeer extends GtkGenericPeer public void paint (Graphics g) { - Component parent = awtComponent.getParent(); - GtkComponentPeer parentPeer = null; - if ((parent instanceof Container) && !parent.isLightweight()) - parentPeer = (GtkComponentPeer) parent.getPeer(); - - addExposeFilter(); - if (parentPeer != null) - parentPeer.addExposeFilter(); - - Rectangle clip = g.getClipBounds(); - gtkWidgetQueueDrawArea(clip.x, clip.y, clip.width, clip.height); - - removeExposeFilter(); - if (parentPeer != null) - parentPeer.removeExposeFilter(); } public Dimension preferredSize () @@ -371,8 +383,11 @@ public class GtkComponentPeer extends GtkGenericPeer 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))); + new Rectangle (x, y, width, height))); } public void requestFocus () @@ -391,7 +406,7 @@ public class GtkComponentPeer extends GtkGenericPeer gtkWidgetSetBackground (c.getRed(), c.getGreen(), c.getBlue()); } - native public void setNativeBounds (int x, int y, int width, int height); + native void setNativeBounds (int x, int y, int width, int height); public void setBounds (int x, int y, int width, int height) { @@ -426,13 +441,24 @@ public class GtkComponentPeer extends GtkGenericPeer if (parent instanceof Window && !lightweightChild) { Insets insets = ((Window) parent).getInsets (); - // Convert from Java coordinates to GTK coordinates. - setNativeBounds (x - insets.left, y - insets.top, width, height); + 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 ()); @@ -448,7 +474,7 @@ public class GtkComponentPeer extends GtkGenericPeer // 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. - gtkSetFont(f.getName(), f.getStyle(), f.getSize()); + gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize()); } public void setForeground (Color c) @@ -488,8 +514,9 @@ public class GtkComponentPeer extends GtkGenericPeer protected void postExposeEvent (int x, int y, int width, int height) { - q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, - new Rectangle (x, y, width, 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, diff --git a/libjava/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkContainerPeer.java index 040499724fd..7fddd56619f 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkContainerPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkContainerPeer.java @@ -45,13 +45,16 @@ import java.awt.Container; import java.awt.Font; import java.awt.Graphics; import java.awt.Insets; +import java.awt.Window; import java.awt.event.PaintEvent; +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) { @@ -59,22 +62,38 @@ public class GtkContainerPeer extends GtkComponentPeer this.c = c; } - public void beginValidate() + public void beginValidate () { + isValidating = true; } - public void endValidate() + public void endValidate () { -// q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, -// new Rectangle (x, y, width, height))); -// Graphics gc = getGraphics (); -// if (gc != null) -// { -// awtComponent.update (gc); -// gc.dispose (); -// } -// System.out.println ("got here"); -// awtComponent.repaint (); + 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() diff --git a/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java index 1d6ce8b8bf0..af22a2723ef 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkDialogPeer.java @@ -42,9 +42,9 @@ import java.awt.AWTEvent; import java.awt.Component; import java.awt.Dialog; import java.awt.Graphics; -import java.awt.peer.DialogPeer; import java.awt.Rectangle; import java.awt.event.PaintEvent; +import java.awt.peer.DialogPeer; public class GtkDialogPeer extends GtkWindowPeer implements DialogPeer @@ -75,11 +75,12 @@ public class GtkDialogPeer extends GtkWindowPeer protected void postExposeEvent (int x, int y, int width, int height) { - q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, - new Rectangle (x + insets.left, - y + insets.top, - width, height))); - } + if (!isInRepaint) + q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, + new Rectangle (x + insets.left, + y + insets.top, + width, height))); + } void create () { diff --git a/libjava/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java index d31e0c5be02..19925568e87 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java @@ -45,8 +45,8 @@ import java.awt.Graphics; import java.awt.Window; import java.awt.event.WindowEvent; import java.awt.peer.FileDialogPeer; -import java.io.FilenameFilter; import java.io.File; +import java.io.FilenameFilter; public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer { @@ -57,7 +57,6 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer private FilenameFilter filter; native void create (GtkContainerPeer parent); - native void connectJObject (); native void connectSignals (); native void nativeSetFile (String file); native public String nativeGetDirectory(); @@ -94,6 +93,7 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer awtComponent.getY (), dims[0], dims[1]); } + super.setComponentBounds (); } public void setFile (String fileName) diff --git a/libjava/gnu/java/awt/peer/gtk/GtkFontPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkFontPeer.java index 5de3301270d..605d738a199 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkFontPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkFontPeer.java @@ -1,5 +1,5 @@ /* GtkFontPeer.java -- Implements FontPeer with GTK+ - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,20 +37,25 @@ 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.awt.peer.FontPeer; -import java.awt.*; -import java.awt.geom.*; -import java.awt.font.*; +import java.text.CharacterIterator; import java.util.Locale; -import java.util.ResourceBundle; import java.util.MissingResourceException; -import java.text.*; -import gnu.java.awt.peer.ClasspathFontPeer; +import java.util.ResourceBundle; public class GtkFontPeer extends ClasspathFontPeer { private static ResourceBundle bundle; - + static { try diff --git a/libjava/gnu/java/awt/peer/gtk/GtkFramePeer.java b/libjava/gnu/java/awt/peer/gtk/GtkFramePeer.java index e1a877eedcb..c0c1437b656 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkFramePeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkFramePeer.java @@ -39,6 +39,7 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; import java.awt.Component; +import java.awt.Container; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; @@ -57,51 +58,72 @@ public class GtkFramePeer extends GtkWindowPeer 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 moveLayout (int offset); - native void gtkLayoutSetVisible (boolean vis); + native void gtkFixedSetVisible (boolean visible); + + int getMenuBarHeight () + { + return menuBar == null ? 0 : getMenuBarHeight (menuBar); + } public void setMenuBar (MenuBar bar) { - if (bar == null) - { - if (menuBar != null) + if (bar == null && menuBar != null) { - gtkLayoutSetVisible(false); - removeMenuBarPeer(); + // We're removing the menubar. + gtkFixedSetVisible (false); menuBar = null; - moveLayout(menuBarHeight); + removeMenuBarPeer (); insets.top -= menuBarHeight; - menuBarHeight = 0; - awtComponent.doLayout(); - gtkLayoutSetVisible(true); + menuBarHeight = 0; + awtComponent.validate (); + gtkFixedSetVisible (true); } - } - else - { - gtkLayoutSetVisible(false); - int oldHeight = 0; - if (menuBar != null) + 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(); - oldHeight = menuBarHeight; - insets.top -= menuBarHeight; + 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); } - menuBar = (MenuBarPeer) ((MenuBar) bar).getPeer(); - setMenuBarPeer(menuBar); - menuBarHeight = getMenuBarHeight (menuBar); - if (oldHeight != menuBarHeight) - moveLayout(oldHeight - menuBarHeight); - insets.top += menuBarHeight; - awtComponent.doLayout(); - gtkLayoutSetVisible(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 @@ -151,7 +173,7 @@ public class GtkFramePeer extends GtkWindowPeer native void nativeSetIconImageFromData (int[] pixels, int width, int height); public void setIconImage (Image image) { - if (image != null) + if (image != null && image instanceof GtkImage) { GtkImage img = (GtkImage) image; // FIXME: Image should be loaded, but if not, do image loading here. @@ -206,15 +228,20 @@ public class GtkFramePeer extends GtkWindowPeer || 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) { @@ -225,10 +252,11 @@ public class GtkFramePeer extends GtkWindowPeer protected void postExposeEvent (int x, int y, int width, int height) { - q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, - new Rectangle (x + insets.left, - y + insets.top, - width, height))); + if (!isInRepaint) + q.postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT, + new Rectangle (x + insets.left, + y + insets.top, + width, height))); } public int getState () diff --git a/libjava/gnu/java/awt/peer/gtk/GtkGenericPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkGenericPeer.java index f7a7b2270ac..657e830bf2e 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkGenericPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkGenericPeer.java @@ -82,4 +82,6 @@ public class GtkGenericPeer // Let's assume this will never wrap. return next_native_state++; } + + native void gtkWidgetModifyFont (String name, int style, int size); } diff --git a/libjava/gnu/java/awt/peer/gtk/GtkImage.java b/libjava/gnu/java/awt/peer/gtk/GtkImage.java index 9234d248aba..510646c5a6a 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkImage.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkImage.java @@ -230,7 +230,7 @@ public class GtkImage extends Image implements ImageConsumer int offset, int scansize) { setPixels (x, y, width, height, cm, convertPixels (pixels), offset, - scansize); + scansize); if (observer != null) observer.imageUpdate (this, @@ -255,7 +255,8 @@ public class GtkImage extends Image implements ImageConsumer if (scansize == width && height == 1) { - System.arraycopy (pixels, offset, + // Copy contents of pixels array into pixel cache. + System.arraycopy (pixels, offset, pixelCache, y * this.width + x, pixels.length - offset); } @@ -274,7 +275,7 @@ public class GtkImage extends Image implements ImageConsumer if (status == ImageConsumer.STATICIMAGEDONE && isCacheable) isLoaded = true; - if (status == ImageConsumer.SINGLEFRAMEDONE) + if (status == ImageConsumer.SINGLEFRAME) isCacheable = false; if (observer != null) @@ -289,7 +290,7 @@ public class GtkImage extends Image implements ImageConsumer -1, -1, -1, -1); } - if (source != null) + if (source != null && status != ImageConsumer.SINGLEFRAME) source.removeConsumer (this); } diff --git a/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java b/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java index d15cb4a4acf..1e5eb4f6ab3 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkImagePainter.java @@ -42,6 +42,7 @@ import java.awt.Color; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; import java.util.Hashtable; public class GtkImagePainter implements Runnable, ImageConsumer @@ -57,10 +58,11 @@ public class GtkImagePainter implements Runnable, ImageConsumer boolean flipX, flipY; Rectangle clip; int s_width, s_height; + ImageObserver observer; public GtkImagePainter (GtkImage image, GdkGraphics gc, int x, int y, - int width, int height, Color bgcolor) + int width, int height, Color bgcolor, ImageObserver o) { this.image = image; this.gc = (GdkGraphics) gc.create (); @@ -74,15 +76,16 @@ public class GtkImagePainter implements Runnable, ImageConsumer flipX = flipY = false; s_width = s_height = 0; clip = null; + observer = o; - new Thread (this).start (); + run (); } public GtkImagePainter (GtkImage image, GdkGraphics gc, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, - Color bgcolor) + Color bgcolor, ImageObserver o) { this.image = image; this.gc = (GdkGraphics) gc.create (); @@ -91,6 +94,7 @@ public class GtkImagePainter implements Runnable, ImageConsumer redBG = bgcolor.getRed (); greenBG = bgcolor.getGreen (); blueBG = bgcolor.getBlue (); + observer = o; this.width = Math.abs (dx2 - dx1); this.height = Math.abs (dy2 - dy1); @@ -105,7 +109,7 @@ public class GtkImagePainter implements Runnable, ImageConsumer s_height = Math.abs (sy2 - sy1); clip = new Rectangle (sx1, sy1, s_width, s_height); - new Thread (this).start (); + run (); } public void @@ -126,7 +130,7 @@ public class GtkImagePainter implements Runnable, ImageConsumer if (model.equals (ColorModel.getRGBdefault ())) return pixels; - + int ret[] = new int[pixels.length]; for (int i = 0; i < pixels.length; i++) @@ -180,6 +184,11 @@ public class GtkImagePainter implements Runnable, ImageConsumer startX + x, startY + y, width, height, convertPixels (pixels, model), offset, scansize, affine); + + if (observer != null) + observer.imageUpdate (image, + ImageObserver.SOMEBITS, + x, y, width, height); } public void @@ -247,5 +256,17 @@ public class GtkImagePainter implements Runnable, ImageConsumer imageComplete (int status) { image.imageComplete(status); + + if (observer != null) + { + if (status == ImageConsumer.IMAGEERROR) + observer.imageUpdate (null, + ImageObserver.ERROR, + -1, -1, -1, -1); + else + observer.imageUpdate (null, + ImageObserver.ALLBITS, + -1, -1, -1, -1); + } } } diff --git a/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java index c28b7f597cc..25473d78ea2 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkLabelPeer.java @@ -47,10 +47,11 @@ public class GtkLabelPeer extends GtkComponentPeer implements LabelPeer { native void create (String text, float alignment); - native void gtkSetFont (String name, int style, int size); + native void gtkWidgetModifyFont (String name, int style, int size); native void nativeSetAlignment (float alignment); native public void setText (String text); + native void setNativeBounds (int x, int y, int width, int height); void create () { diff --git a/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java index a85aba952fd..13055d33c27 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkListPeer.java @@ -41,8 +41,8 @@ package gnu.java.awt.peer.gtk; import java.awt.AWTEvent; import java.awt.Dimension; import java.awt.List; -import java.awt.event.MouseEvent; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.awt.peer.ListPeer; public class GtkListPeer extends GtkComponentPeer @@ -58,9 +58,8 @@ public class GtkListPeer extends GtkComponentPeer } native void create (int rows); - native void connectJObject (); native void connectSignals (); - native void gtkSetFont (String name, int style, int size); + native void gtkWidgetModifyFont (String name, int style, int size); native void gtkWidgetRequestFocus (); native void getSize (int rows, int visibleRows, int dims[]); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java index b9cca1a5c38..90ad0c01b59 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java @@ -38,8 +38,10 @@ 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; @@ -53,15 +55,25 @@ public class GtkMenuBarPeer extends GtkMenuComponentPeer public GtkMenuBarPeer (MenuBar target) { super (target); - create (); } - native void nativeSetHelpMenu(MenuPeer menuPeer); + 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()); + // nativeSetHelpMenu((MenuPeer) menu.getPeer()); } native public void delMenu (int index); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java index 92f02230621..dd061ed37b8 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java @@ -38,15 +38,28 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; +import java.awt.Font; +import java.awt.MenuComponent; 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/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java index c32839ec6ba..81da90df012 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java @@ -38,24 +38,31 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; +import java.awt.Font; import java.awt.Menu; +import java.awt.MenuComponent; import java.awt.MenuBar; import java.awt.MenuItem; -import java.awt.peer.MenuItemPeer; -import java.awt.peer.MenuComponentPeer; import java.awt.peer.MenuBarPeer; +import java.awt.peer.MenuComponentPeer; +import java.awt.peer.MenuItemPeer; import java.awt.peer.MenuPeer; public class GtkMenuItemPeer extends GtkMenuComponentPeer implements MenuItemPeer { native void create (String label); - public native void connectSignals (); + native void connectSignals (); + native void gtkWidgetModifyFont (String name, int style, int size); + + void create () + { + create (((MenuItem) awtWidget).getLabel()); + } public GtkMenuItemPeer (MenuItem item) { super (item); - create (item.getLabel ()); setEnabled (item.isEnabled ()); setParent (item); @@ -63,6 +70,21 @@ public class GtkMenuItemPeer extends GtkMenuComponentPeer 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 diff --git a/libjava/gnu/java/awt/peer/gtk/GtkPanelPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkPanelPeer.java index 0b5d0af4342..fbdfcf472ca 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkPanelPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkPanelPeer.java @@ -47,7 +47,6 @@ public class GtkPanelPeer extends GtkContainerPeer implements PanelPeer { native void create (); - native void connectJObject (); public GtkPanelPeer (Panel p) { diff --git a/libjava/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java b/libjava/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java index d0cbde034e2..233bed75a9b 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java @@ -54,7 +54,7 @@ public class GtkScrollPanePeer extends GtkContainerPeer create (awtComponent.getWidth (), awtComponent.getHeight ()); } - native void gtkScrolledWindowSetScrollPosition(int x, int y); + // native void gtkScrolledWindowSetScrollPosition(int x, int y); native void gtkScrolledWindowSetHScrollIncrement (int u); native void gtkScrolledWindowSetVScrollIncrement (int u); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java index 0e1b65137d7..ef4289633c4 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java @@ -60,7 +60,6 @@ public class GtkScrollbarPeer extends GtkComponentPeer int min, int max, int stepIncr, int pageIncr, int visibleAmount); - native void connectJObject (); native void connectSignals (); public GtkScrollbarPeer (Scrollbar s) diff --git a/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java index b08728b2bff..94874deb617 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java @@ -52,7 +52,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer native void create (int width, int height, int scrollbarVisibility); - native void gtkSetFont (String name, int style, int size); + native void gtkWidgetModifyFont (String name, int style, int size); native void gtkWidgetRequestFocus (); void create () @@ -68,11 +68,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer awtComponent.setFont (f); } - FontMetrics fm; - if (GtkToolkit.useGraphics2D ()) - fm = new GdkClasspathFontPeerMetrics (f); - else - fm = new GdkFontMetrics (f); + FontMetrics fm = getFontMetrics (f); TextArea ta = ((TextArea) awtComponent); int sizeRows = ta.getRows (); @@ -130,11 +126,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer if (f == null) return new Dimension (width, height); - FontMetrics fm; - if (GtkToolkit.useGraphics2D ()) - fm = new GdkClasspathFontPeerMetrics (f); - else - fm = new GdkFontMetrics (f); + FontMetrics fm = getFontMetrics (f); int sizeRows = rows == 0 ? DEFAULT_ROWS : rows; int sizeCols = cols == 0 ? DEFAULT_COLS : cols; @@ -163,11 +155,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer if (f == null) return new Dimension (width, height); - FontMetrics fm; - if (GtkToolkit.useGraphics2D ()) - fm = new GdkClasspathFontPeerMetrics (f); - else - fm = new GdkFontMetrics (f); + FontMetrics fm = getFontMetrics (f); int sizeRows = rows == 0 ? DEFAULT_ROWS : rows; int sizeCols = cols == 0 ? DEFAULT_COLS : cols; diff --git a/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java index d4a702deb35..bd1ac812470 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java @@ -66,11 +66,7 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer awtComponent.setFont (f); } - FontMetrics fm; - if (GtkToolkit.useGraphics2D ()) - fm = new GdkClasspathFontPeerMetrics (f); - else - fm = new GdkFontMetrics (f); + FontMetrics fm = getFontMetrics (f); TextField tf = ((TextField) awtComponent); int cols = tf.getColumns (); @@ -84,7 +80,7 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer native int gtkEntryGetBorderWidth (); - native void gtkSetFont (String name, int style, int size); + native void gtkWidgetModifyFont (String name, int style, int size); public GtkTextFieldPeer (TextField tf) { @@ -117,11 +113,7 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer if (f == null) return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]); - FontMetrics fm; - if (GtkToolkit.useGraphics2D ()) - fm = new GdkClasspathFontPeerMetrics (f); - else - fm = new GdkFontMetrics (f); + FontMetrics fm = getFontMetrics (f); int text_width = cols * fm.getMaxAdvance (); @@ -140,11 +132,7 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer if (f == null) return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]); - FontMetrics fm; - if (GtkToolkit.useGraphics2D ()) - fm = new GdkClasspathFontPeerMetrics (f); - else - fm = new GdkFontMetrics (f); + FontMetrics fm = getFontMetrics (f); int text_width = cols * fm.getMaxAdvance (); diff --git a/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java b/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java index 3f82159c3ab..def22e9874e 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -1,5 +1,5 @@ /* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers - Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,36 +38,40 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; +import gnu.classpath.Configuration; +import gnu.java.awt.EmbeddedWindow; +import gnu.java.awt.EmbeddedWindowSupport; +import gnu.java.awt.peer.ClasspathFontPeer; +import gnu.java.awt.peer.ClasspathTextLayoutPeer; +import gnu.java.awt.peer.EmbeddedWindowPeer; +import gnu.java.awt.peer.gtk.GdkPixbufDecoder; + 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.font.TextAttribute; import java.awt.im.InputMethodHighlight; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; -import java.awt.image.ImageObserver; import java.awt.image.ImageConsumer; +import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; -import java.awt.GraphicsEnvironment; import java.awt.peer.*; 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.Map; import java.util.MissingResourceException; import java.util.Properties; -import gnu.java.awt.EmbeddedWindow; -import gnu.java.awt.EmbeddedWindowSupport; -import gnu.java.awt.peer.EmbeddedWindowPeer; -import gnu.java.awt.peer.ClasspathFontPeer; -import gnu.classpath.Configuration; -import gnu.java.awt.peer.gtk.GdkPixbufDecoder; /* 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 + 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. */ @@ -79,7 +83,6 @@ import gnu.java.awt.peer.gtk.GdkPixbufDecoder; * drawing contexts. Any other value will cause the older GdkGraphics * object to be used. */ - public class GtkToolkit extends gnu.java.awt.ClasspathToolkit implements EmbeddedWindowSupport { @@ -87,7 +90,6 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit Hashtable containers = new Hashtable(); static EventQueue q = new EventQueue(); static Clipboard systemClipboard; - static boolean useGraphics2dSet; static boolean useGraphics2d; @@ -120,14 +122,21 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public int checkImage (Image image, int width, int height, ImageObserver observer) { - int status = ((GtkImage) image).checkImage (); + int status = ImageObserver.ALLBITS + | ImageObserver.WIDTH + | ImageObserver.HEIGHT; + + if (image instanceof GtkImage) + { + status = ((GtkImage) image).checkImage (); + } if (observer != null) observer.imageUpdate (image, status, -1, -1, image.getWidth (observer), image.getHeight (observer)); - + return status; } @@ -304,22 +313,59 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit "SansSerif" }); } + private class LRUCache extends java.util.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) { - if (useGraphics2D()) - return new GdkClasspathFontPeerMetrics (font); + if (metricsCache.containsKey(font)) + return (FontMetrics) metricsCache.get(font); else - return new GdkFontMetrics (font); + { + FontMetrics m; + m = new GdkFontMetrics (font); + metricsCache.put(font, m); + return m; + } } public Image getImage (String filename) { - return createImage (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) { - return createImage (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) @@ -510,8 +556,10 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit */ private FontPeer getFontPeer (String name, int style, int size) { - GtkFontPeer fp = new GtkFontPeer (name, style, size); - return fp; + Map attrs = new HashMap (); + ClasspathFontPeer.copyStyleToAttrs (style, attrs); + ClasspathFontPeer.copySizeToAttrs (size, attrs); + return getClasspathFontPeer (name, attrs); } /** @@ -522,40 +570,28 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public ClasspathFontPeer getClasspathFontPeer (String name, Map attrs) { - if (useGraphics2D()) - return new GdkClasspathFontPeer (name, 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 { - // Default values - int size = 12; - int style = Font.PLAIN; - if (name == null) - name = "Default"; - - if (attrs.containsKey (TextAttribute.WEIGHT)) - { - Float weight = (Float) attrs.get (TextAttribute.WEIGHT); - if (weight.floatValue () >= TextAttribute.WEIGHT_BOLD.floatValue ()) - style += Font.BOLD; - } - - if (attrs.containsKey (TextAttribute.POSTURE)) - { - Float posture = (Float) attrs.get (TextAttribute.POSTURE); - if (posture.floatValue () >= TextAttribute.POSTURE_OBLIQUE.floatValue ()) - style += Font.ITALIC; - } - - if (attrs.containsKey (TextAttribute.SIZE)) - { - Float fsize = (Float) attrs.get (TextAttribute.SIZE); - size = fsize.intValue(); - } - - return (ClasspathFontPeer) this.getFontPeer (name, style, size); + 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() { return q; diff --git a/libjava/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/libjava/gnu/java/awt/peer/gtk/GtkWindowPeer.java index a2357699b3c..c61eecd5aa5 100644 --- a/libjava/gnu/java/awt/peer/gtk/GtkWindowPeer.java +++ b/libjava/gnu/java/awt/peer/gtk/GtkWindowPeer.java @@ -40,8 +40,8 @@ package gnu.java.awt.peer.gtk; import java.awt.Component; import java.awt.Dimension; -import java.awt.Window; import java.awt.Frame; +import java.awt.Window; import java.awt.event.WindowEvent; import java.awt.peer.WindowPeer; @@ -106,7 +106,6 @@ public class GtkWindowPeer extends GtkContainerPeer { } - native void connectJObject (); native void connectSignals (); public GtkWindowPeer (Window window) diff --git a/libjava/gnu/java/beans/IntrospectionIncubator.java b/libjava/gnu/java/beans/IntrospectionIncubator.java index 21bf984d24c..ac08f7ae5cd 100644 --- a/libjava/gnu/java/beans/IntrospectionIncubator.java +++ b/libjava/gnu/java/beans/IntrospectionIncubator.java @@ -99,7 +99,8 @@ public class IntrospectionIncubator { * @param method The method instance to examine. */ public void addMethod(Method method) { - if(Modifier.isPublic(method.getModifiers())) { + if(Modifier.isPublic(method.getModifiers()) && + !Modifier.isStatic(method.getModifiers())) { String name = ClassHelper.getTruncatedName(method.getName()); Class retType = method.getReturnType(); Class[] params = method.getParameterTypes(); |