aboutsummaryrefslogtreecommitdiff
path: root/libjava/java
diff options
context:
space:
mode:
authorRolf W. Rasmussen <rolfwr@ii.uib.no>2000-07-25 19:53:30 +0200
committerRolf Rasmussen <rolfwr@gcc.gnu.org>2000-07-25 17:53:30 +0000
commit69b1b29156c348ffd39c85043b21d0ffd6cb4a73 (patch)
tree63ee8beca6a86986c9b97b7ab1cf2dced5a16fb5 /libjava/java
parent4c31fe99c3f0d0c94771ec3ff8ee08840b7c553a (diff)
downloadgcc-69b1b29156c348ffd39c85043b21d0ffd6cb4a73.zip
gcc-69b1b29156c348ffd39c85043b21d0ffd6cb4a73.tar.gz
gcc-69b1b29156c348ffd39c85043b21d0ffd6cb4a73.tar.bz2
ColorModel.java: New file...
2000-07-23 Rolf W. Rasmussen <rolfwr@ii.uib.no> * libjava/java/awt/image/ColorModel.java: New file, replaces the stub libjava/java/awt/ColorModel.java which was located in the wrong package. * libjava/java/awt/image/ComponentColorModel.java: New file. * libjava/java/awt/image/ComponentSampleModel.java: New file. * libjava/java/awt/image/DataBuffer.java: New file. * libjava/java/awt/image/DataBufferByte.java: New file. * libjava/java/awt/image/DataBufferInt.java: New file. * libjava/java/awt/image/DataBufferUShort.java: New file. * libjava/java/awt/image/DirectColorModel.java: New file. * libjava/java/awt/image/PackedColorModel.java: New file. * libjava/java/awt/image/Raster.java: New file. * libjava/java/awt/image/SampleModel.java: New file. * libjava/java/awt/image/SinglePixelPackedSampleModel.java: New file. * libjava/java/awt/image/IndexColorModel.java: New file. * libjava/java/awt/image/ImageConsumer.java: Removed import of java.awt.ColorModel stub. * gnu/gcj/util/BitMaskExtent.java: New file, utility class. * gnu/gcj/util/Buffers.java: New file, utility class. * libjava/Makefile.am: Updated to include new files. * libjava/Makefile.in: Rebuilt. From-SVN: r35245
Diffstat (limited to 'libjava/java')
-rw-r--r--libjava/java/awt/ColorModel.java20
-rw-r--r--libjava/java/awt/color/ColorSpace.java111
-rw-r--r--libjava/java/awt/color/ICC_ColorSpace.java53
-rw-r--r--libjava/java/awt/color/ICC_Profile.java40
-rw-r--r--libjava/java/awt/image/ColorModel.java575
-rw-r--r--libjava/java/awt/image/ComponentColorModel.java303
-rw-r--r--libjava/java/awt/image/ComponentSampleModel.java435
-rw-r--r--libjava/java/awt/image/DataBuffer.java177
-rw-r--r--libjava/java/awt/image/DataBufferByte.java103
-rw-r--r--libjava/java/awt/image/DataBufferInt.java103
-rw-r--r--libjava/java/awt/image/DataBufferUShort.java103
-rw-r--r--libjava/java/awt/image/DirectColorModel.java338
-rw-r--r--libjava/java/awt/image/ImageConsumer.java1
-rw-r--r--libjava/java/awt/image/IndexColorModel.java355
-rw-r--r--libjava/java/awt/image/PackedColorModel.java162
-rw-r--r--libjava/java/awt/image/Raster.java418
-rw-r--r--libjava/java/awt/image/SampleModel.java436
-rw-r--r--libjava/java/awt/image/SinglePixelPackedSampleModel.java245
-rw-r--r--libjava/java/awt/image/WritableRaster.java234
19 files changed, 4191 insertions, 21 deletions
diff --git a/libjava/java/awt/ColorModel.java b/libjava/java/awt/ColorModel.java
deleted file mode 100644
index 0e58df1..0000000
--- a/libjava/java/awt/ColorModel.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (C) 2000 Free Software Foundation
-
- This file is part of libgcj.
-
-This software is copyrighted work licensed under the terms of the
-Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
-details. */
-
-package java.awt;
-
-/* Status: Just a placeholder. */
-
-public class ColorModel implements Transparency
-{
- public int getTransparency()
- {
- // FIXME
- return 0;
- }
-}
diff --git a/libjava/java/awt/color/ColorSpace.java b/libjava/java/awt/color/ColorSpace.java
new file mode 100644
index 0000000..e6e1251
--- /dev/null
+++ b/libjava/java/awt/color/ColorSpace.java
@@ -0,0 +1,111 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.color;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public abstract class ColorSpace
+{
+ public static final int TYPE_XYZ = 0;
+ public static final int TYPE_Lab = 1;
+ public static final int TYPE_Luv = 2;
+ public static final int TYPE_YCbCr = 3;
+ public static final int TYPE_Yxy = 4;
+ public static final int TYPE_RGB = 5;
+ public static final int TYPE_GRAY = 6;
+ public static final int TYPE_HSV = 7;
+ public static final int TYPE_HLS = 8;
+ public static final int TYPE_CMYK = 9;
+ // mysterious gap in the enumeration sequenece
+ public static final int TYPE_CMY = 11;
+ public static final int TYPE_2CLR = 12;
+ public static final int TYPE_3CLR = 13;
+ public static final int TYPE_4CLR = 14;
+ public static final int TYPE_5CLR = 15;
+ public static final int TYPE_6CLR = 16;
+ public static final int TYPE_7CLR = 17;
+ public static final int TYPE_8CLR = 18;
+ public static final int TYPE_9CLR = 19;
+ public static final int TYPE_ACLR = 20;
+ public static final int TYPE_BCLR = 21;
+ public static final int TYPE_CCLR = 22;
+ public static final int TYPE_DCLR = 23;
+ public static final int TYPE_ECLR = 24;
+ public static final int TYPE_FCLR = 25;
+
+ public static final int CS_sRGB = 1000;
+ public static final int CS_CIEXYZ = 1001;
+ public static final int CS_PYCC = 1002;
+ public static final int CS_GRAY = 1003;
+ public static final int CS_LINEAR_RGB = 1004;
+
+ private static final int CS_BASE = CS_sRGB;
+ private static final int CS_END = CS_LINEAR_RGB+1;
+ private static final int CS_COUNT = CS_END - CS_BASE;
+
+ // Instances are lazily instantiated
+ private static final ColorSpace[] INSTANCES = new ColorSpace[CS_COUNT];
+
+ private int type;
+ private int numcomponents;
+ protected ColorSpace(int type, int numcomponents)
+ {
+ this.type = type;
+ this.numcomponents = numcomponents;
+ }
+
+ public static ColorSpace getInstance(int colorspace)
+ {
+ if ((colorspace >= CS_BASE) && (colorspace < CS_END))
+ {
+ int instanceIndex = colorspace - CS_BASE;
+ if (INSTANCES[instanceIndex] == null)
+ {
+ ICC_Profile profile = new ICC_Profile(colorspace);
+ INSTANCES[instanceIndex] = new ICC_ColorSpace(profile);
+ }
+ return INSTANCES[instanceIndex];
+ }
+ throw new IllegalArgumentException("unknown/unsupported colorspace");
+ }
+
+ public boolean isCS_sRGB()
+ {
+ return false;
+ }
+
+ public abstract float[] toRGB(float[] colorvalue);
+
+ public abstract float[] fromRGB(float[] rgbvalue);
+
+ public abstract float[] toCIEXYZ(float[] colorvalue);
+
+ public abstract float[] fromCIEXYZ(float[] colorvalue);
+
+ public int getType()
+ {
+ return type;
+ }
+
+ public int getNumComponents()
+ {
+ return numcomponents;
+ }
+
+ public String getName(int idx)
+ {
+ return "type " + type;
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + "[type=" + type + "]";
+ }
+}
diff --git a/libjava/java/awt/color/ICC_ColorSpace.java b/libjava/java/awt/color/ICC_ColorSpace.java
new file mode 100644
index 0000000..90ff88c
--- /dev/null
+++ b/libjava/java/awt/color/ICC_ColorSpace.java
@@ -0,0 +1,53 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.color;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class ICC_ColorSpace extends ColorSpace
+{
+ private ICC_Profile profile;
+
+ public ICC_ColorSpace(ICC_Profile profile)
+ {
+ super(CS_sRGB, profile.getNumComponents());
+
+ this.profile = profile;
+ }
+
+ public ICC_Profile getProfile()
+ {
+ return profile;
+ }
+
+ public float[] toRGB(float[] colorvalue)
+ {
+ // FIXME: Always assumes sRGB:
+ return colorvalue;
+ }
+
+ public float[] fromRGB(float[] rgbvalue)
+ {
+ // FIXME: Always assumes sRGB:
+ return rgbvalue;
+ }
+
+ public float[] toCIEXYZ(float[] colorvalue)
+ {
+ // FIXME: Not implemented
+ throw new UnsupportedOperationException();
+ }
+
+ public float[] fromCIEXYZ(float[] colorvalue)
+ {
+ // FIXME: Not implemented
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/libjava/java/awt/color/ICC_Profile.java b/libjava/java/awt/color/ICC_Profile.java
new file mode 100644
index 0000000..475aa55
--- /dev/null
+++ b/libjava/java/awt/color/ICC_Profile.java
@@ -0,0 +1,40 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.color;
+
+// Currently just a stub.
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class ICC_Profile
+{
+ long profileID; // why long?
+
+ ICC_Profile(long profileID)
+ {
+ this.profileID = profileID;
+ }
+
+ public int getNumComponents()
+ {
+ switch (profileID)
+ {
+ case ColorSpace.CS_sRGB:
+ case ColorSpace.CS_LINEAR_RGB:
+ case ColorSpace.CS_CIEXYZ:
+ return 3;
+ case ColorSpace.CS_GRAY:
+ return 1;
+ case ColorSpace.CS_PYCC: // have no clue about this one
+ default:
+ throw new UnsupportedOperationException("profile not implemented");
+ }
+ }
+}
diff --git a/libjava/java/awt/image/ColorModel.java b/libjava/java/awt/image/ColorModel.java
new file mode 100644
index 0000000..ceee278
--- /dev/null
+++ b/libjava/java/awt/image/ColorModel.java
@@ -0,0 +1,575 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import gnu.gcj.awt.Buffers;
+
+/**
+ * A color model operates with colors in several formats:
+ *
+ * <ul>
+ * <li>normalized: component samples are in range [0.0, 1.0].</li>
+ *
+ * <li>color model pixel value: all the color component samples for a
+ * sigle pixel packed/encoded in a way natural for the color
+ * model.</li>
+ *
+ * <li>color model pixel int value: only makes sense if the natural
+ * encoding of a single pixel can fit in a single int value.</li>
+ *
+ * <li>array of transferType containing a single pixel: the pixel is
+ * encoded in the natural way of the color model, taking up as many
+ * array elements as needed.</li>
+ *
+ * <li>sRGB pixel int value: a pixel in sRGB color space, encoded in
+ * default 0xAARRGGBB format, assumed not alpha premultiplied.</li>
+ *
+ * <li>single [0, 255] scaled int samples from default sRGB color
+ * space. These are always assumed to be alpha non-premultiplied.</li>
+ *
+ * <li>arrays of unnormalized component samples of single pixel: these
+ * samples are scaled and multiplied according to the color model, but
+ * is otherwise not packed or encoded. Each element of the array is one
+ * seperate component sample. The color model only operate on the
+ * components from one pixel at a time, but using offsets, allows
+ * manipulation of arrays that contain the components of more than one
+ * pixel.</li>
+ *
+ * </ul>
+ *
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+
+public abstract class ColorModel implements Transparency
+{
+ protected int pixel_bits;
+ protected int transferType;
+
+ private int[] bits;
+ private ColorSpace cspace;
+ private int transparency;
+ private boolean hasAlpha;
+ private boolean isAlphaPremultiplied;
+
+ static int[] nArray(int value, int times)
+ {
+ int[] array = new int[times];
+ java.util.Arrays.fill(array, value);
+ return array;
+ }
+
+ static byte[] nArray(byte value, int times)
+ {
+ byte[] array = new byte[times];
+ java.util.Arrays.fill(array, value);
+ return array;
+ }
+
+ public ColorModel(int bits)
+ {
+ this(bits * 4, // total bits, sRGB, four channels
+ nArray(bits, 4), // bits for each channel
+ null, // FIXME: should be sRGB
+ true, // has alpha
+ false, // not premultiplied
+ TRANSLUCENT,
+ Buffers.smallestAppropriateTransferType(bits * 4));
+ }
+
+ protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
+ boolean hasAlpha, boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ this.pixel_bits = pixel_bits;
+ this.bits = bits;
+ this.cspace = cspace;
+ this.hasAlpha = hasAlpha;
+ this.isAlphaPremultiplied = isAlphaPremultiplied;
+ this.transparency = transparency;
+ this.transferType = transferType;
+ }
+
+ public static ColorModel getRGBdefault()
+ {
+ return new DirectColorModel(8, 0xff0000, 0xff00, 0xff, 0xff000000);
+ }
+
+ public final boolean hasAlpha()
+ {
+ return hasAlpha;
+ }
+
+ public final boolean isAlphaPremultiplied()
+ {
+ return isAlphaPremultiplied;
+ }
+
+ public int getPixelSize()
+ {
+ return pixel_bits;
+ }
+
+ public int getComponentSize(int componentIdx)
+ {
+ return bits[componentIdx];
+ }
+
+ public int[] getComponentSize()
+ {
+ return bits;
+ }
+
+ public int getTransparency()
+ {
+ return transparency;
+ }
+
+ public int getNumComponents()
+ {
+ return getNumColorComponents() + (hasAlpha ? 1 : 0);
+ }
+
+ public int getNumColorComponents()
+ {
+ return cspace.getNumComponents();
+ }
+
+ /**
+ * Converts pixel value to sRGB and extract red int sample scaled
+ * to range [0, 255].
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model, (assumed alpha premultiplied if color model says
+ * so.)
+ *
+ * @return red sample scaled to range [0, 255], from default color
+ * space sRGB, alpha non-premultiplied.
+ */
+ public abstract int getRed(int pixel);
+
+ /**
+ * Converts pixel value to sRGB and extract green int sample
+ * scaled to range [0, 255].
+ *
+ * @see #getRed(int)
+ */
+ public abstract int getGreen(int pixel);
+
+ /**
+ * Converts pixel value to sRGB and extract blue int sample
+ * scaled to range [0, 255].
+ *
+ * @see #getRed(int)
+ */
+ public abstract int getBlue(int pixel);
+
+ /**
+ * Extract alpha int sample from pixel value, scaled to [0, 255].
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model.
+ *
+ * @return alpha sample, scaled to range [0, 255].
+ */
+ public abstract int getAlpha(int pixel);
+
+ /**
+ * Converts a pixel int value of the color space of the color
+ * model to a sRGB pixel int value.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param pixel pixel value that will be interpreted according to
+ * the color model.
+ *
+ * @return a pixel in sRGB color space, encoded in default
+ * 0xAARRGGBB format. */
+ public int getRGB(int pixel)
+ {
+ return
+ ((getAlpha(pixel) & 0xff) << 24) |
+ (( getRed(pixel) & 0xff) << 16) |
+ ((getGreen(pixel) & 0xff) << 8) |
+ (( getBlue(pixel) & 0xff) << 0);
+ }
+
+
+ /**
+ * In this color model we know that the whole pixel value will
+ * always be contained within the first element of the pixel
+ * array.
+ */
+ final int getPixelFromArray(Object inData) {
+ DataBuffer data =
+ Buffers.createBufferFromData(transferType, inData, 1);
+ Object da = Buffers.getData(data);
+
+ return data.getElem(0);
+ }
+
+ /**
+ * Converts pixel in the given array to sRGB and extract blue int
+ * sample scaled to range [0-255].
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ */
+ public int getRed(Object inData)
+ {
+ return getRed(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getGreen(Object inData)
+ {
+ return getGreen(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getBlue(Object inData) {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ /**
+ * @see #getRed(Object)
+ */
+ public int getAlpha(Object inData) {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ /**
+ * Converts a pixel in the given array of the color space of the
+ * color model to an sRGB pixel int value.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getDataElements(int rgb, Object pixel)</code>.
+ * I.e. <code>(rgb == cm.getRGB(cm.getDataElements(rgb,
+ * null)))</code>.
+ *
+ * @param inData array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @return a pixel in sRGB color space, encoded in default
+ * 0xAARRGGBB format.
+ *
+ * @see #getDataElements(int, Object)
+ */
+ public int getRGB(Object inData)
+ {
+ return
+ ((getAlpha(inData) & 0xff) << 24) |
+ (( getRed(inData) & 0xff) << 16) |
+ ((getGreen(inData) & 0xff) << 8) |
+ (( getBlue(inData) & 0xff) << 0);
+ }
+
+ /**
+ * Converts an sRGB pixel int value to an array containing a
+ * single pixel of the color space of the color model.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getRGB(Object inData)</code>.
+ *
+ * Outline of conversion process:
+ *
+ * <ol>
+ *
+ * <li>Convert rgb to normalized [0.0, 1.0] sRGB values.</li>
+ *
+ * <li>Convert to color space components using fromRGB in
+ * ColorSpace.</li>
+ *
+ * <li>If color model has alpha and should be premultiplied,
+ * multiply color space components with alpha value</li>
+ *
+ * <li>Scale the components to the correct number of bits.</li>
+ *
+ * <li>Arrange the components in the output array</li>
+ *
+ * </ol>
+ *
+ * @param rgb The color to be converted to dataElements. A pixel
+ * in sRGB color space, encoded in default 0xAARRGGBB format,
+ * assumed not alpha premultiplied.
+ *
+ * @param pixel to avoid needless creation of arrays, an array to
+ * use to return the pixel can be given. If null, a suitable array
+ * will be created.
+ *
+ * @return An array of transferType values representing the color,
+ * in the color model format. The color model defines whether the
+ *
+ * @see #getRGB(Object)
+ */
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // FIXME: implement
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from a
+ * pixel value. I.e. decompose the pixel, but not perform any
+ * color conversion.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param pixel pixel value encoded according to the color model.
+ *
+ * @return arrays of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are
+ * according to the color model. Each component sample is stored
+ * as a seperate element in the array.
+ */
+ public int[] getComponents(int pixel, int[] components, int offset) {
+ // FIXME: implement
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from an
+ * array of transferType containing a single pixel. I.e. decompose
+ * the pixel, but not perform any color conversion.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @return arrays of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are
+ * according to the color model. Each component sample is stored
+ * as a seperate element in the array.
+ */
+ public int[] getComponents(Object pixel, int[] components, int offset)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Convert normalized components to unnormalized components.
+ */
+ public int[] getUnnormalizedComponents(float[] normComponents,
+ int normOffset,
+ int[] components,
+ int offset)
+ {
+ int numComponents = getNumComponents();
+ if (components == null)
+ {
+ components = new int[offset + numComponents];
+ }
+
+ for (int i=0; i<numComponents; i++)
+ {
+ float in = normComponents[normOffset++];
+ int out = (int) (in * ((2<<getComponentSize(i)) - 1));
+ components[offset++] = out;
+ }
+ return components;
+ }
+
+ /**
+ * Convert unnormalized components to normalized components.
+ */
+ public float[] getNormalizedComponents(int[] components,
+ int offset,
+ float[] normComponents,
+ int normOffset)
+ {
+ int numComponents = getNumComponents();
+ if (normComponents == null)
+ {
+ normComponents = new float[normOffset + numComponents];
+ }
+
+ for (int i=0; i<numComponents; i++)
+ {
+ float in = components[offset++];
+ float out = in / ((2<<getComponentSize(i)) - 1);
+ normComponents[normOffset++] = out;
+ }
+ return normComponents;
+ }
+
+ /**
+ * Converts the unnormalized component samples from an array to a
+ * pixel value. I.e. composes the pixel from component samples, but
+ * does not perform any color conversion or scaling of the samples.
+ *
+ * This method performs the inverse function of
+ * <code>getComponents(int pixel, int[] components,
+ * int offset)</code>. I.e.
+ *
+ * <code>(pixel == cm.getDataElement(cm.getComponents(pixel, null,
+ * 0), 0))</code>.
+ *
+ * This method is typically overriden in subclasses to provide a
+ * more efficient implementation.
+ *
+ * @param arrays of unnormalized component samples of single
+ * pixel. The scale and multiplication state of the samples are
+ * according to the color model. Each component sample is stored
+ * as a seperate element in the array.
+ *
+ * @return pixel value encoded according to the color model.
+ */
+ public int getDataElement(int[] components, int offset)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ColorModel)) return false;
+
+ ColorModel o = (ColorModel) obj;
+ return
+ (pixel_bits == o.pixel_bits) &&
+ (transferType == o.transferType) &&
+ (transparency == o.transparency) &&
+ (hasAlpha == o.hasAlpha) &&
+ (isAlphaPremultiplied == isAlphaPremultiplied) &&
+ (bits.equals(o.bits)) &&
+ (cspace.equals(o.cspace));
+ }
+
+ public final ColorSpace getColorSpace()
+ {
+ return cspace;
+ }
+
+ // Typically overridden
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ return this;
+
+ int w = raster.getWidth();
+ int h = raster.getHeight();
+ int x = raster.getMinX();
+ int y = raster.getMinY();
+ int size = w*h;
+ int numColors = getNumColorComponents();
+ int numComponents = getNumComponents();
+ int alphaScale = (1<<getComponentSize(numColors)) - 1;
+ double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);
+
+ for (int i=0; i<size; i++)
+ {
+ double alpha = pixels[i*numComponents+numColors]*alphaScale;
+ for (int c=0; c<numColors; c++)
+ {
+ int offset = i*numComponents+c;
+ if (isAlphaPremultiplied)
+ pixels[offset] = pixels[offset]/alpha;
+ else
+ pixels[offset] = pixels[offset]*alpha;
+ }
+ }
+
+ raster.setPixels(0, 0, w, h, pixels);
+
+ // FIXME: what can we return?
+ return null;
+ }
+
+ // Typically overridden
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ SampleModel sampleModel = raster.getSampleModel();
+ return isCompatibleSampleModel(sampleModel);
+ }
+
+ // Typically overridden
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ return new WritableRaster(createCompatibleSampleModel(w, h),
+ new Point(0, 0));
+ }
+
+ // Typically overridden
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // Typically overridden
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return sm.getTransferType() == transferType;
+ }
+
+ public void finalize() {
+ }
+
+ /**
+ * Subclasses must override this method if it is possible for the
+ * color model to have an alpha channel.
+ *
+ * @return null, as per JDK 1.3 doc. Subclasses will only return
+ * null if no alpha raster exists.
+ */
+ public WritableRaster getAlphaRaster(WritableRaster raster)
+ {
+ return null;
+
+ /* It is a mystery to me why we couldn't use the following code...
+
+
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+
+
+ ...here, and avoided overriding the method in subclasses,
+ but the Sun docs state that this method always will return
+ null, and that overriding is required. Oh, well.
+ */
+ }
+
+ String stringParam()
+ {
+ return "pixel_bits=" + pixel_bits +
+ ", cspace=" + cspace +
+ ", transferType=" + transferType +
+ ", transparency=" + transparency +
+ ", hasAlpha=" + hasAlpha +
+ ", isAlphaPremultiplied=" + isAlphaPremultiplied;
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + "[" + stringParam() + "]";
+ }
+}
diff --git a/libjava/java/awt/image/ComponentColorModel.java b/libjava/java/awt/image/ComponentColorModel.java
new file mode 100644
index 0000000..deb40ff
--- /dev/null
+++ b/libjava/java/awt/image/ComponentColorModel.java
@@ -0,0 +1,303 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import java.awt.color.*;
+import java.awt.Point;
+import gnu.gcj.awt.Buffers;
+
+public class ComponentColorModel extends ColorModel
+{
+ private static int sum(int[] values)
+ {
+ int sum = 0;
+ for (int i=0; i<values.length; i++)
+ sum += values[i];
+ return sum;
+ }
+
+ public ComponentColorModel(ColorSpace colorSpace, int[] bits,
+ boolean hasAlpha,
+ boolean isAlphaPremultiplied,
+ int transparency, int transferType)
+ {
+ super(sum(bits), bits, colorSpace, hasAlpha, isAlphaPremultiplied,
+ transparency, transferType);
+ }
+
+ public int getRed(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getGreen(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getBlue(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return (int) getRGBFloat(pixel)[0];
+ }
+
+ public int getAlpha(int pixel)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ int shift = 8 - getComponentSize(getNumColorComponents());
+ if (shift >= 0) return pixel << shift;
+ return pixel >> (-shift);
+ }
+
+ public int getRGB(int pixel)
+ {
+ float[] rgb = getRGBFloat(pixel);
+ int ret = getRGB(rgb);
+ if (hasAlpha()) ret |= getAlpha(pixel) << 24;
+ return ret;
+ }
+
+
+ /* FIXME: Is the values returned from toRGB() in the [0.0, 1.0] or the
+ [0.0, 256) range?
+
+ we assume it is in the [0.0, 1.0] range along with the
+ other color spaces. */
+
+ /* Note, it's OK to pass a to large array to toRGB(). Extra
+ elements are ignored. */
+
+ private float[] getRGBFloat(int pixel)
+ {
+ float[] data = { pixel };
+ return cspace.toRGB(data);
+ }
+
+ private float[] getRGBFloat(Object inData)
+ {
+ DataBuffer buffer =
+ Buffers.createBufferFromData(transferType, inData,
+ getNumComponents());
+ int colors = getNumColorComponents();
+ float[] data = new float[colors];
+
+ // FIXME: unpremultiply data that is premultiplied
+ for (int i=0; i<colors; i++)
+ {
+ float maxValue = (1<<getComponentSize(i))-1;
+ data[i] = buffer.getElemFloat(i)/maxValue;
+ }
+ float[] rgb = cspace.toRGB(data);
+ return rgb;
+ }
+
+ public int getRed(Object inData)
+ {
+ return (int) getRGBFloat(inData)[0]*255;
+ }
+
+ public int getGreen(Object inData)
+ {
+ return (int) getRGBFloat(inData)[1]*255;
+ }
+
+ public int getBlue(Object inData)
+ {
+ return (int) getRGBFloat(inData)[2]*255;
+ }
+
+ public int getAlpha(Object inData)
+ {
+ DataBuffer buffer =
+ Buffers.createBufferFromData(transferType, inData,
+ getNumComponents());
+ int shift = 8 - getComponentSize(getNumColorComponents());
+ int alpha = buffer.getElem(getNumColorComponents());
+ if (shift >= 0) return alpha << shift;
+ return alpha >> (-shift);
+ }
+
+ private int getRGB(float[] rgb)
+ {
+ /* NOTE: We could cast to byte instead of int here. This would
+ avoid bits spilling over from one bit field to
+ another. But, if we assume that floats are in the [0.0,
+ 1.0] range, this will never happen anyway. */
+
+ /* Remember to multiply BEFORE casting to int, otherwise, decimal
+ point data will be lost. */
+ int ret =
+ (((int) (rgb[0]*255F)) << 16) |
+ (((int) (rgb[1]*255F)) << 8) |
+ (((int) (rgb[2]*255F)) << 0);
+ return ret;
+ }
+
+ /**
+ * @param inData pixel data of transferType, as returned by the
+ * getDataElements method in SampleModel.
+ */
+ public int getRGB(Object inData)
+ {
+ float[] rgb = getRGBFloat(inData);
+ int ret = getRGB(rgb);
+ if (hasAlpha()) ret |= getAlpha(inData) << 24;
+ return ret;
+ }
+
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // Convert rgb to [0.0, 1.0] sRGB values.
+ float[] rgbFloats = {
+ ((rgb >> 16)&0xff)/255.0F,
+ ((rgb >> 8)&0xff)/255.0F,
+ ((rgb >> 0)&0xff)/255.0F
+ };
+
+ // Convert from rgb to color space components.
+ float[] data = cspace.fromRGB(rgbFloats);
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
+ getNumComponents());
+ int numColors = getNumColorComponents();
+
+ if (hasAlpha())
+ {
+ float alpha = ((rgb >> 24)&0xff)/255.0F;
+
+ /* If color model has alpha and should be premultiplied, multiply
+ color space components with alpha value. */
+ if (isAlphaPremultiplied()) {
+ for (int i=0; i<numColors; i++)
+ data[i] *= alpha;
+ }
+ // Scale the alpha sample to the correct number of bits.
+ alpha *= (1<<(bits[numColors]-1));
+ // Arrange the alpha sample in the output array.
+ buffer.setElemFloat(numColors, alpha);
+ }
+ for (int i=0; i<numColors; i++)
+ {
+ // Scale the color samples to the correct number of bits.
+ float value = data[i]*(1<<(bits[i]-1));
+ // Arrange the color samples in the output array.
+ buffer.setElemFloat(i, value);
+ }
+ return Buffers.getData(buffer);
+ }
+
+ public int[] getComponents(int pixel, int[] components, int offset)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ if (components == null)
+ components = new int[getNumComponents() + offset];
+ components[offset] = pixel;
+ return components;
+ }
+
+ public int[] getComponents(Object pixel, int[] components, int offset)
+ {
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel,
+ getNumComponents());
+ int numComponents = getNumComponents();
+
+ if (components == null)
+ components = new int[numComponents + offset];
+
+ for (int i=0; i<numComponents; i++)
+ components[offset++] = buffer.getElem(i);
+
+ return components;
+ }
+
+ public int getDataElement(int[] components, int offset)
+ {
+ if (getNumComponents()>1) throw new IllegalArgumentException();
+ return components[offset];
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ DataBuffer buffer = Buffers.createBuffer(transferType, obj,
+ getNumComponents());
+ int numComponents = getNumComponents();
+
+ for (int i=0; i<numComponents; i++)
+ buffer.setElem(i, components[offset++]);
+
+ return Buffers.getData(buffer);
+ }
+
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied) {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ return this;
+
+ /* TODO: provide better implementation based on the
+ assumptions we can make due to the specific type of the
+ color model. */
+ super.coerceData(raster, isAlphaPremultiplied);
+
+ return new ComponentColorModel(cspace, bits, hasAlpha(),
+ isAlphaPremultiplied, // argument
+ transparency, transferType);
+ }
+
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ return super.isCompatibleRaster(raster);
+ // FIXME: Should we test something more here? (Why override?)
+ }
+
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ SampleModel sm = createCompatibleSampleModel(w, h);
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(sm, origin);
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ int pixelStride = getNumComponents();
+
+ /* TODO: Maybe we don't need to create a new offset array each
+ time, but rather use the same array every time. */
+ int[] bandOffsets = new int[pixelStride];
+ for (int i=0; i<pixelStride; i++) bandOffsets[i] = i;
+ return new ComponentSampleModel(transferType, w, h,
+ pixelStride, pixelStride*w,
+ bandOffsets);
+ }
+
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return
+ (sm instanceof ComponentSampleModel) &&
+ super.isCompatibleSampleModel(sm);
+ }
+
+ public WritableRaster getAlphaRaster(WritableRaster raster)
+ {
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ComponentColorModel)) return false;
+ return super.equals(obj);
+ }
+}
diff --git a/libjava/java/awt/image/ComponentSampleModel.java b/libjava/java/awt/image/ComponentSampleModel.java
new file mode 100644
index 0000000..f825d48
--- /dev/null
+++ b/libjava/java/awt/image/ComponentSampleModel.java
@@ -0,0 +1,435 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import gnu.gcj.awt.Buffers;
+
+/* FIXME: This class does not yet support data type TYPE_SHORT */
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class ComponentSampleModel extends SampleModel
+{
+ protected int[] bandOffsets;
+ protected int[] bankIndices;
+
+ // FIXME: Should we really shadow the numBands in the superclass?
+ //protected int numBands;
+
+ /** Used when creating data buffers. */
+ protected int numBanks;
+
+ protected int scanlineStride;
+
+ protected int pixelStride;
+
+ private boolean tightPixelPacking = false;
+
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int[] bandOffsets)
+ {
+ this(dataType, w, h, pixelStride, scanlineStride,
+ new int[bandOffsets.length], bandOffsets);
+ }
+
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int[] bankIndices,
+ int[] bandOffsets)
+ {
+ super(dataType, w, h, bandOffsets.length);
+ if ((pixelStride<0) || (scanlineStride<0) ||
+ (bandOffsets.length<1) ||
+ (bandOffsets.length != bankIndices.length))
+ throw new IllegalArgumentException();
+
+ this.bandOffsets = bandOffsets;
+ this.bankIndices = bankIndices;
+
+ for (int b=0; b<bankIndices.length; b++)
+ this.numBanks = Math.max(this.numBanks, bankIndices[b]+1);
+
+ this.scanlineStride = scanlineStride;
+ this.pixelStride = pixelStride;
+
+ // See if we can use some speedups
+
+ /* FIXME: May these checks should be reserved for the
+ PixelInterleavedSampleModel? */
+
+ if (pixelStride == numBands)
+ {
+ tightPixelPacking = true;
+ for (int b=0; b<numBands; b++) {
+ if ((bandOffsets[b] != b) || (bankIndices[b] !=0))
+ {
+ tightPixelPacking = false;
+ break;
+ }
+ }
+ }
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ return new ComponentSampleModel(dataType, w, h, pixelStride,
+ scanlineStride, bankIndices,
+ bandOffsets);
+ }
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ int numBands = bands.length;
+
+ int[] bankIndices = new int[numBands];
+ int[] bandOffsets = new int[numBands];
+ for (int b=0; b<numBands; b++)
+ {
+ bankIndices[b] = this.bankIndices[bands[b]];
+ bandOffsets[b] = this.bandOffsets[bands[b]];
+ }
+
+ return new ComponentSampleModel(dataType, width, height, pixelStride,
+ scanlineStride, bankIndices,
+ bandOffsets);
+ }
+
+ public DataBuffer createDataBuffer()
+ {
+ // Maybe this value should be precalculated in the constructor?
+ int highestOffset = 0;
+ for (int b=0; b<numBands; b++)
+ {
+ highestOffset = Math.max(highestOffset, bandOffsets[b]);
+ }
+ int size = pixelStride*(width-1) + scanlineStride*(height-1) +
+ highestOffset + 1;
+
+ return Buffers.createBuffer(getDataType(), size, numBanks);
+ }
+
+ public int getOffset(int x, int y)
+ {
+ return getOffset(x, y, 0);
+ }
+
+ public int getOffset(int x, int y, int b)
+ {
+ return bandOffsets[b] + pixelStride*x + scanlineStride*y;
+ }
+
+ public final int[] getSampleSize()
+ {
+ int size = DataBuffer.getDataTypeSize(getDataType());
+ int[] sizes = new int[numBands];
+
+ java.util.Arrays.fill(sizes, size);
+ return sizes;
+ }
+
+ public final int getSampleSize(int band)
+ {
+ return DataBuffer.getDataTypeSize(getDataType());
+ }
+
+ public final int[] getBankIndices()
+ {
+ return bankIndices;
+ }
+
+ public final int[] getBandOffsets()
+ {
+ return bandOffsets;
+ }
+
+ public final int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ public final int getPixelStride()
+ {
+ return pixelStride;
+ }
+
+ public final int getNumDataElements()
+ {
+ return numBands;
+ }
+
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int xyOffset = pixelStride*x + scanlineStride*y;
+
+ int[] totalBandDataOffsets = new int[numBands];
+
+ /* Notice that band and bank offsets are different. Band offsets
+ are managed by the sample model, and bank offsets are managed
+ by the data buffer. Both must be accounted for. */
+
+ /* FIXME: For single pixels, it is probably easier to simple
+ call getElem instead of calculating the bank offset ourself.
+
+ On the other hand, then we need to push the value through
+ the int type returned by the getElem method. */
+
+ int[] bankOffsets = data.getOffsets();
+
+ for (int b=0; b<numBands; b++)
+ {
+ totalBandDataOffsets[b] =
+ bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset;
+ }
+
+ try
+ {
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ DataBufferByte inByte = (DataBufferByte) data;
+ byte[] outByte = (byte[]) obj;
+ if (outByte == null) outByte = new byte[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outByte[b] = inByte.getData(bankIndices[b])[dOffset];
+ }
+ return outByte;
+
+ case DataBuffer.TYPE_USHORT:
+ DataBufferUShort inUShort = (DataBufferUShort) data;
+ short[] outUShort = (short[]) obj;
+ if (outUShort == null) outUShort = new short[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
+ }
+ return outUShort;
+
+ case DataBuffer.TYPE_INT:
+ DataBufferInt inInt = (DataBufferInt) data;
+ int[] outInt = (int[]) obj;
+ if (outInt == null) outInt = new int[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ int dOffset = totalBandDataOffsets[b];
+ outInt[b] = inInt.getData(bankIndices[b])[dOffset];
+ }
+ return outInt;
+
+ // FIXME: Fill in the other possible types.
+ default:
+ throw new IllegalStateException("unknown transfer type " +
+ getTransferType());
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While reading data elements, " +
+ "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
+ ", data.getSize()=" + data.getSize() + ": " + aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ public Object getDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data)
+ {
+ if (!tightPixelPacking)
+ {
+ return super.getDataElements(x, y, w, h, obj, data);
+ }
+
+ // using get speedup
+
+ // We can copy whole rows
+ int rowSize = w*numBands;
+ int dataSize = rowSize*h;
+
+ DataBuffer transferBuffer =
+ Buffers.createBuffer(getTransferType(), obj, dataSize);
+ obj = Buffers.getData(transferBuffer);
+
+ int inOffset =
+ pixelStride*x +
+ scanlineStride*y +
+ data.getOffset(); // Assumes only one band is used
+
+ /* We don't add band offsets since we assume that bands have
+ offsets 0, 1, 2, ... */
+
+ // See if we can copy everything in one go
+ if (scanlineStride == rowSize)
+ {
+ // Collapse scan lines:
+ rowSize *= h;
+ // We ignore scanlineStride since it won't be of any use
+ h = 1;
+ }
+
+ int outOffset = 0;
+ Object inArray = Buffers.getData(data);
+ for (int yd = 0; yd<h; yd++)
+ {
+ System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
+ inOffset += scanlineStride;
+ outOffset += rowSize;
+ }
+ return obj;
+ }
+
+ public void setDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data)
+ {
+ if (!tightPixelPacking)
+ {
+ super.setDataElements(x, y, w, h, obj, data);
+ return;
+ }
+
+ // using set speedup, we can copy whole rows
+ int rowSize = w*numBands;
+ int dataSize = rowSize*h;
+
+ DataBuffer transferBuffer =
+ Buffers.createBufferFromData(getTransferType(), obj, dataSize);
+
+ int[] bankOffsets = data.getOffsets();
+
+ int outOffset =
+ pixelStride*x +
+ scanlineStride*y +
+ bankOffsets[0]; // same assuptions as in get...
+
+ // See if we can copy everything in one go
+ if (scanlineStride == rowSize)
+ {
+ // Collapse scan lines:
+ scanlineStride = rowSize *= h;
+ h = 1;
+ }
+
+ int inOffset = 0;
+ Object outArray = Buffers.getData(data);
+ for (int yd = 0; yd<h; yd++)
+ {
+ System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
+ outOffset += scanlineStride;
+ inOffset += rowSize;
+ }
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ if (iArray == null) iArray = new int[numBands];
+ for (int b=0; b<numBands; b++)
+ {
+ iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]);
+ }
+ return iArray;
+ }
+
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ if (iArray == null) iArray = new int[numBands*w*h];
+ int outOffset = 0;
+ for (y=0; y<h; y++)
+ {
+ int lineOffset = offset;
+ for (x=0; x<w; x++)
+ {
+ for (int b=0; b<numBands; b++)
+ {
+ iArray[outOffset++] =
+ data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
+ }
+ lineOffset += pixelStride;
+ }
+ offset += scanlineStride;
+ }
+ return iArray;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ return data.getElem(bankIndices[b], getOffset(x, y, b));
+ }
+
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ int[] totalBandDataOffsets = new int[numBands];
+ int[] bankOffsets = data.getOffsets();
+ for (int b=0; b<numBands; b++)
+ totalBandDataOffsets[b] =
+ bandOffsets[b]+bankOffsets[bankIndices[b]] + offset;
+
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+
+ for (int b=0; b<numBands; b++)
+ out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
+
+ return;
+ }
+ default:
+ throw new UnsupportedOperationException("transfer type not " +
+ "implemented");
+ }
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = pixelStride*x + scanlineStride*y;
+ for (int b=0; b<numBands; b++)
+ data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]);
+ }
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ data.setElem(bankIndices[b], getOffset(x, y, b), s);
+ }
+}
diff --git a/libjava/java/awt/image/DataBuffer.java b/libjava/java/awt/image/DataBuffer.java
new file mode 100644
index 0000000..b40dac1
--- /dev/null
+++ b/libjava/java/awt/image/DataBuffer.java
@@ -0,0 +1,177 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+/**
+ * Class that manages arrays of data elements. A data buffer consists
+ * of one or more banks. A bank is a continuous region of data
+ * elements.
+ *
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public abstract class DataBuffer
+{
+ public static final int TYPE_BYTE = 0;
+ public static final int TYPE_USHORT = 1;
+ public static final int TYPE_SHORT = 2;
+ public static final int TYPE_INT = 3;
+ public static final int TYPE_FLOAT = 4;
+ public static final int TYPE_DOUBLE = 5;
+ public static final int TYPE_UNDEFINED = 32;
+
+ /** The type of the data elements stored in the data buffer. */
+ protected int dataType;
+
+ /** The number of banks in this buffer. */
+ protected int banks = 1;
+
+ /** Offset into the default (0'th) bank). */
+ protected int offset; // FIXME: Is offsets[0] always mirrored in offset?
+
+ /** The size of the banks. */
+ protected int size;
+
+ /** Offset into each bank. */
+ protected int[] offsets;
+
+ protected DataBuffer(int dataType, int size)
+ {
+ this.dataType = dataType;
+ this.size = size;
+ }
+
+ protected DataBuffer(int dataType, int size, int numBanks) {
+ this(dataType, size);
+ banks = numBanks;
+ offsets = new int[numBanks];
+ }
+
+ protected DataBuffer(int dataType, int size, int numBanks, int offset) {
+ this(dataType, size, numBanks);
+
+ java.util.Arrays.fill(offsets, offset);
+
+ this.offset = offset;
+ }
+
+ protected DataBuffer(int dataType, int size, int numBanks, int[] offsets) {
+ this(dataType, size);
+ if (numBanks != offsets.length)
+ throw new ArrayIndexOutOfBoundsException();
+
+ banks = numBanks;
+ this.offsets = offsets;
+
+ offset = offsets[0];
+ }
+
+ public static int getDataTypeSize(int dataType) {
+ // Maybe this should be a lookup table instead.
+ switch (dataType)
+ {
+ case TYPE_BYTE:
+ return 8;
+ case TYPE_USHORT:
+ case TYPE_SHORT:
+ return 16;
+ case TYPE_INT:
+ case TYPE_FLOAT:
+ return 32;
+ case TYPE_DOUBLE:
+ return 64;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public int getDataType()
+ {
+ return dataType;
+ }
+
+ public int getSize()
+ {
+ return size;
+ }
+
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ public int[] getOffsets()
+ {
+ if (offsets == null)
+ {
+ // is this necessary?
+ offsets = new int[1];
+ offsets[0] = offset;
+ }
+ return offsets;
+ }
+
+ public int getNumBanks()
+ {
+ return banks;
+ }
+
+ public int getElem(int i)
+ {
+ return getElem(0, i);
+ }
+
+ public abstract int getElem(int bank, int i);
+
+ public void setElem(int i, int val)
+ {
+ setElem(0, i, val);
+ }
+
+ public abstract void setElem(int bank, int i, int val);
+
+ public float getElemFloat(int i)
+ {
+ return getElem(i);
+ }
+
+ public float getElemFloat(int bank, int i)
+ {
+ return getElem(bank, i);
+ }
+
+ public void setElemFloat(int i, float val)
+ {
+ setElem(i, (int) val);
+ }
+
+ public void setElemFloat(int bank, int i, float val)
+ {
+ setElem(bank, i, (int) val);
+ }
+
+ public double getElemDouble(int i)
+ {
+ return getElem(i);
+ }
+
+ public double getElemDouble(int bank, int i)
+ {
+ return getElem(bank, i);
+ }
+
+ public void setElemDouble(int i, double val)
+ {
+ setElem(i, (int) val);
+ }
+
+ public void setElemDouble(int bank, int i, double val)
+ {
+ setElem(bank, i, (int) val);
+ }
+}
diff --git a/libjava/java/awt/image/DataBufferByte.java b/libjava/java/awt/image/DataBufferByte.java
new file mode 100644
index 0000000..67b4f5f
--- /dev/null
+++ b/libjava/java/awt/image/DataBufferByte.java
@@ -0,0 +1,103 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class DataBufferByte extends DataBuffer
+{
+ private byte[] data;
+ private byte[][] bankData;
+
+ public DataBufferByte(int size)
+ {
+ super(TYPE_BYTE, size);
+ data = new byte[size];
+ }
+
+ public DataBufferByte(int size, int numBanks)
+ {
+ super(TYPE_BYTE, size, numBanks);
+ bankData = new byte[numBanks][size];
+ data = bankData[0];
+ }
+
+ public DataBufferByte(byte[] dataArray, int size)
+ {
+ super(TYPE_BYTE, size);
+ data = dataArray;
+ }
+
+ public DataBufferByte(byte[] dataArray, int size, int offset)
+ {
+ super(TYPE_BYTE, size, 1, offset);
+ data = dataArray;
+ }
+
+ public DataBufferByte(byte[][] dataArray, int size)
+ {
+ super(TYPE_BYTE, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ public DataBufferByte(byte[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_BYTE, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ public byte[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ public byte[][] getBankData()
+ {
+ return bankData;
+ }
+
+ public int getElem(int i)
+ {
+ return data[i+offset] & 0xff; // get unsigned byte as int
+ }
+
+ public int getElem(int bank, int i)
+ {
+ // get unsigned byte as int
+ return bankData[bank][i+offsets[bank]] & 0xff;
+ }
+
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (byte) val;
+ }
+
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (byte) val;
+ }
+}
diff --git a/libjava/java/awt/image/DataBufferInt.java b/libjava/java/awt/image/DataBufferInt.java
new file mode 100644
index 0000000..560fb9c
--- /dev/null
+++ b/libjava/java/awt/image/DataBufferInt.java
@@ -0,0 +1,103 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class DataBufferInt extends DataBuffer
+{
+ private int[] data;
+ private int[][] bankData;
+
+ public DataBufferInt(int size)
+ {
+ super(TYPE_INT, size);
+ data = new int[size];
+ }
+
+ public DataBufferInt(int size, int numBanks)
+ {
+ super(TYPE_INT, size, numBanks);
+ bankData = new int[numBanks][size];
+ data = bankData[0];
+ }
+
+ public DataBufferInt(int[] dataArray, int size)
+ {
+ super(TYPE_INT, size);
+ data = dataArray;
+ }
+
+ public DataBufferInt(int[] dataArray, int size, int offset)
+ {
+ super(TYPE_INT, size, 1, offset);
+ data = dataArray;
+ }
+
+ public DataBufferInt(int[][] dataArray, int size)
+ {
+ super(TYPE_INT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ public DataBufferInt(int[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_INT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ public int[] getData()
+ {
+ return data;
+ }
+
+ public int[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ public int[][] getBankData()
+ {
+ return bankData;
+ }
+
+ public int getElem(int i)
+ {
+ return data[i+offset];
+ }
+
+ public int getElem(int bank, int i)
+ {
+ // get unsigned int as int
+ return bankData[bank][i+offsets[bank]];
+ }
+
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (int) val;
+ }
+
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (int) val;
+ }
+}
diff --git a/libjava/java/awt/image/DataBufferUShort.java b/libjava/java/awt/image/DataBufferUShort.java
new file mode 100644
index 0000000..7963c38
--- /dev/null
+++ b/libjava/java/awt/image/DataBufferUShort.java
@@ -0,0 +1,103 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+/* This is one of several classes that are nearly identical. Maybe we
+ should have a central template and generate all these files. This
+ is one of the cases where templates or macros would have been
+ useful to have in Java.
+
+ This file has been created using search-replace. My only fear is
+ that these classes will grow out-of-sync as of a result of changes
+ that are not propagated to the other files. As always, mirroring
+ code is a maintenance nightmare. */
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class DataBufferUShort extends DataBuffer
+{
+ private short[] data;
+ private short[][] bankData;
+
+ public DataBufferUShort(int size)
+ {
+ super(TYPE_USHORT, size);
+ data = new short[size];
+ }
+
+ public DataBufferUShort(int size, int numBanks)
+ {
+ super(TYPE_USHORT, size, numBanks);
+ bankData = new short[numBanks][size];
+ data = bankData[0];
+ }
+
+ public DataBufferUShort(short[] dataArray, int size)
+ {
+ super(TYPE_USHORT, size);
+ data = dataArray;
+ }
+
+ public DataBufferUShort(short[] dataArray, int size, int offset)
+ {
+ super(TYPE_USHORT, size, 1, offset);
+ data = dataArray;
+ }
+
+ public DataBufferUShort(short[][] dataArray, int size)
+ {
+ super(TYPE_USHORT, size, dataArray.length);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ public DataBufferUShort(short[][] dataArray, int size, int[] offsets)
+ {
+ super(TYPE_USHORT, size, dataArray.length, offsets);
+ bankData = dataArray;
+ data = bankData[0];
+ }
+
+ public short[] getData()
+ {
+ return data;
+ }
+
+ public short[] getData(int bank)
+ {
+ return bankData[bank];
+ }
+
+ public short[][] getBankData()
+ {
+ return bankData;
+ }
+
+ public int getElem(int i)
+ {
+ return data[i+offset] & 0xffff; // get unsigned short as int
+ }
+
+ public int getElem(int bank, int i)
+ {
+ // get unsigned short as int
+ return bankData[bank][i+offsets[bank]] & 0xffff;
+ }
+
+ public void setElem(int i, int val)
+ {
+ data[i+offset] = (short) val;
+ }
+
+ public void setElem(int bank, int i, int val)
+ {
+ bankData[bank][i+offsets[bank]] = (short) val;
+ }
+}
diff --git a/libjava/java/awt/image/DirectColorModel.java b/libjava/java/awt/image/DirectColorModel.java
new file mode 100644
index 0000000..8e092d1
--- /dev/null
+++ b/libjava/java/awt/image/DirectColorModel.java
@@ -0,0 +1,338 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import gnu.gcj.awt.Buffers;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class DirectColorModel extends PackedColorModel
+{
+ public DirectColorModel(int pixelBits, int rmask, int gmask, int bmask)
+ {
+ this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
+ rmask, gmask, bmask, 0,
+ false, // not alpha premultiplied
+ Buffers.smallestAppropriateTransferType(pixelBits) // find type
+ );
+ }
+
+ public DirectColorModel(int pixelBits,
+ int rmask, int gmask, int bmask, int amask)
+ {
+ this(ColorSpace.getInstance(ColorSpace.CS_sRGB), pixelBits,
+ rmask, gmask, bmask, amask,
+ false, // not alpha premultiplied
+ Buffers.smallestAppropriateTransferType(pixelBits) // find type
+ );
+ }
+
+ public DirectColorModel(ColorSpace cspace, int pixelBits,
+ int rmask, int gmask, int bmask, int amask,
+ boolean isAlphaPremultiplied,
+ int transferType)
+ {
+ super(cspace, pixelBits,
+ rmask, gmask, bmask, amask, isAlphaPremultiplied,
+ ((amask == 0) ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
+ transferType);
+ }
+
+ public final int getRedMask()
+ {
+ return getMask(0);
+ }
+
+ public final int getGreenMask()
+ {
+ return getMask(1);
+ }
+
+ public final int getBlueMask()
+ {
+ return getMask(2);
+ }
+
+ public final int getAlphaMask()
+ {
+ return hasAlpha() ? getMask(3) : 0;
+ }
+
+ public final int getRed(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 0);
+ }
+
+ public final int getGreen(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 1);
+ }
+
+ public final int getBlue(int pixel)
+ {
+ return extractAndNormalizeSample(pixel, 2);
+ }
+
+ public final int getAlpha(int pixel)
+ {
+ if (!hasAlpha()) return 0;
+ return extractAndScaleSample(pixel, 3);
+ }
+
+ private final int extractAndNormalizeSample(int pixel, int component)
+ {
+ int value = extractAndScaleSample(pixel, component);
+ if (hasAlpha() && isAlphaPremultiplied())
+ value = value*255/getAlpha(pixel);
+ return value;
+ }
+
+ private final int extractAndScaleSample(int pixel, int component)
+ {
+ int field = pixel & getMask(component);
+ int to8BitShift =
+ 8 - shifts[component] - getComponentSize(component);
+ return (to8BitShift>0) ?
+ (field << to8BitShift) :
+ (field >>> (-to8BitShift));
+ }
+
+
+ /* FIXME: The Sun docs show that this method is overridden, but I don't
+ see any way to improve on the superclass implementation. */
+ public final int getRGB(int pixel)
+ {
+ return super.getRGB(pixel);
+ }
+
+ public int getRed(Object inData)
+ {
+ return getRed(getPixelFromArray(inData));
+ }
+
+ public int getGreen(Object inData)
+ {
+ return getGreen(getPixelFromArray(inData));
+ }
+
+ public int getBlue(Object inData)
+ {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ public int getAlpha(Object inData)
+ {
+ return getAlpha(getPixelFromArray(inData));
+ }
+
+ public int getRGB(Object inData)
+ {
+ return getRGB(getPixelFromArray(inData));
+ }
+
+ /**
+ * Converts a normalized pixel int value in the sRGB color
+ * space to an array containing a single pixel of the color space
+ * of the color model.
+ *
+ * <p>This method performs the inverse function of
+ * <code>getRGB(Object inData)</code>.
+ *
+ * @param rgb pixel as a normalized sRGB, 0xAARRGGBB value.
+ *
+ * @param pixel to avoid needless creation of arrays, an array to
+ * use to return the pixel can be given. If null, a suitable array
+ * will be created.
+ *
+ * @return array of transferType containing a single pixel. The
+ * pixel should be encoded in the natural way of the color model.
+ *
+ * @see #getRGB(Object)
+ */
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ // FIXME: handle alpha multiply
+
+ int pixelValue = 0;
+ int a = 0;
+ if (hasAlpha()) {
+ a = (rgb >>> 24) & 0xff;
+ pixelValue = valueToField(a, 3, 8);
+ }
+
+ if (hasAlpha() && isAlphaPremultiplied())
+ {
+ int r, g, b;
+ /* if r=0xff and a=0xff, then resulting
+ value will be (r*a)>>>8 == 0xfe... This seems wrong.
+ We should divide by 255 rather than shifting >>>8 after
+ multiplying.
+
+ Too bad, shifting is probably less expensive.
+ r = ((rgb >>> 16) & 0xff)*a;
+ g = ((rgb >>> 8) & 0xff)*a;
+ b = ((rgb >>> 0) & 0xff)*a; */
+ /* The r, g, b values we calculate are 16 bit. This allows
+ us to avoid discarding the lower 8 bits obtained if
+ multiplying with the alpha band. */
+
+ // using 16 bit values
+ r = ((rgb >>> 8) & 0xff00)*a/255;
+ g = ((rgb >>> 0) & 0xff00)*a/255;
+ b = ((rgb << 8) & 0xff00)*a/255;
+ pixelValue |=
+ valueToField(r, 0, 16) | // Red
+ valueToField(g, 1, 16) | // Green
+ valueToField(b, 2, 16); // Blue
+ }
+ else
+ {
+ int r, g, b;
+ // using 8 bit values
+ r = (rgb >>> 16) & 0xff;
+ g = (rgb >>> 8) & 0xff;
+ b = (rgb >>> 0) & 0xff;
+
+ pixelValue |=
+ valueToField(r, 0, 8) | // Red
+ valueToField(g, 1, 8) | // Green
+ valueToField(b, 2, 8); // Blue
+ }
+
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ /**
+ * Converts a value to the correct field bits based on the
+ * information derived from the field masks.
+ *
+ * @param highBit the position of the most significant bit in the
+ * val parameter.
+ */
+ private final int valueToField(int val, int component, int highBit)
+ {
+ int toFieldShift =
+ getComponentSize(component) + shifts[component] - highBit;
+ int ret = (toFieldShift>0) ?
+ (val << toFieldShift) :
+ (val >>> (-toFieldShift));
+ return ret & getMask(component);
+ }
+
+ /**
+ * Converts a 16 bit value to the correct field bits based on the
+ * information derived from the field masks.
+ */
+ private final int value16ToField(int val, int component)
+ {
+ int toFieldShift = getComponentSize(component) + shifts[component] - 16;
+ return (toFieldShift>0) ?
+ (val << toFieldShift) :
+ (val >>> (-toFieldShift));
+ }
+
+ /**
+ * Fills an array with the unnormalized component samples from a
+ * pixel value. I.e. decompose the pixel, but not perform any
+ * color conversion.
+ */
+ public final int[] getComponents(int pixel, int[] components, int offset)
+ {
+ int numComponents = getNumComponents();
+ if (components == null) components = new int[offset + numComponents];
+
+ for (int b=0; b<numComponents; b++)
+ components[offset++] = (pixel&getMask(b)) >>> shifts[b];
+
+ return components;
+ }
+
+ public final int[] getComponents(Object pixel, int[] components,
+ int offset)
+ {
+ return getComponents(getPixelFromArray(pixel), components, offset);
+ }
+
+ public final WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ SampleModel sm = createCompatibleSampleModel(w, h);
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(sm, origin);
+ }
+
+ public int getDataElement(int[] components, int offset)
+ {
+ int numComponents = getNumComponents();
+ int pixelValue = 0;
+
+ for (int c=0; c<numComponents; c++)
+ pixelValue |= (components[offset++] << shifts[c]) & getMask(c);
+
+ return pixelValue;
+ }
+
+ public Object getDataElements(int[] components, int offset, Object obj)
+ {
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ int pixelValue = getDataElement(components, offset);
+
+ DataBuffer buffer = Buffers.createBuffer(transferType, obj, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ public ColorModel coerceData(WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ return this;
+
+ /* TODO: provide better implementation based on the
+ assumptions we can make due to the specific type of the
+ color model. */
+ super.coerceData(raster, isAlphaPremultiplied);
+
+ return new ComponentColorModel(cspace, bits, hasAlpha(),
+ isAlphaPremultiplied, // argument
+ transparency, transferType);
+ }
+
+ public boolean isCompatibleRaster(Raster raster)
+ {
+ /* FIXME: the Sun docs say this method is overridden here,
+ but I don't see any way to improve upon the implementation
+ in ColorModel. */
+ return super.isCompatibleRaster(raster);
+ }
+
+ String stringParam()
+ {
+ return super.stringParam() +
+ ", redMask=" + Integer.toHexString(getRedMask()) +
+ ", greenMask=" + Integer.toHexString(getGreenMask()) +
+ ", blueMask=" + Integer.toHexString(getBlueMask()) +
+ ", alphaMask=" + Integer.toHexString(getAlphaMask());
+ }
+
+ public String toString()
+ {
+ /* FIXME: Again, docs say override, but how do we improve upon the
+ superclass implementation? */
+ return super.toString();
+ }
+}
diff --git a/libjava/java/awt/image/ImageConsumer.java b/libjava/java/awt/image/ImageConsumer.java
index 37214d7..26519cb 100644
--- a/libjava/java/awt/image/ImageConsumer.java
+++ b/libjava/java/awt/image/ImageConsumer.java
@@ -8,7 +8,6 @@ details. */
package java.awt.image;
import java.util.Hashtable;
-import java.awt.ColorModel;
public interface ImageConsumer
{
diff --git a/libjava/java/awt/image/IndexColorModel.java b/libjava/java/awt/image/IndexColorModel.java
new file mode 100644
index 0000000..e35fcd6
--- /dev/null
+++ b/libjava/java/awt/image/IndexColorModel.java
@@ -0,0 +1,355 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import gnu.gcj.awt.Buffers;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class IndexColorModel extends ColorModel
+{
+ private byte[] r;
+ private byte[] g;
+ private byte[] b;
+ private byte[] a;
+ private int[] argb;
+ private byte[] cmap;
+ private int start;
+ private int transparent;
+ private int size;
+
+ public IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b)
+ {
+ super(bits, nArray(bits, 3),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ false, // no transparency
+ false, // no premultiplied
+ Transparency.OPAQUE,
+ Buffers.smallestAppropriateTransferType(bits));
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.size = size;
+ }
+
+ public IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b,
+ int transparent)
+ {
+ super(bits, nArray(bits, 4),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ true, // has transparency
+ false,
+ Transparency.BITMASK,
+ Buffers.smallestAppropriateTransferType(bits));
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.transparent = transparent;
+ this.size = size;
+ }
+
+ public IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b,
+ byte[] a)
+ {
+ super(bits, nArray(bits, 4),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ true, // has transparency
+ false,
+ Transparency.BITMASK,
+ Buffers.smallestAppropriateTransferType(bits));
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ this.size = size;
+ }
+
+ public IndexColorModel(int bits, int size, byte[] cmap, int start,
+ boolean hasAlpha)
+ {
+ super(bits, nArray(bits, hasAlpha ? 4 : 3),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ hasAlpha,
+ false,
+ hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE,
+ Buffers.smallestAppropriateTransferType(bits));
+ this.cmap = cmap;
+ this.start = start;
+ this.size = size;
+ }
+
+ public IndexColorModel(int bits, int size, byte[] cmap, int start,
+ boolean hasAlpha, int transparent,
+ int transferType)
+ {
+ super(bits, nArray(bits, hasAlpha ? 4 : 3),
+ ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ hasAlpha,
+ false,
+ hasAlpha ?
+ Transparency.TRANSLUCENT :
+ ((transparent < 0) ?
+ Transparency.OPAQUE :
+ Transparency.BITMASK),
+ transferType);
+ this.cmap = cmap;
+ this.start = start;
+ this.size = size;
+ }
+
+ public final int getMapSize()
+ {
+ return size;
+ }
+
+ public final int getTransparentPixel()
+ {
+ return transparent;
+ }
+
+ public final void getReds(byte r[])
+ {
+ if (this.r == null) calcRGBArrays();
+ System.arraycopy(this.r, 0, r, 0, getMapSize());
+ }
+
+ public final void getGreens(byte g[])
+ {
+ if (this.g == null) calcRGBArrays();
+ System.arraycopy(this.g, 0, g, 0, getMapSize());
+ }
+
+ public final void getBlues(byte b[])
+ {
+ if (this.b == null) calcRGBArrays();
+ System.arraycopy(this.b, 0, b, 0, getMapSize());
+ }
+
+ public final void getAlphas(byte a[])
+ {
+ if (this.a == null) calcAlphaArray();
+ System.arraycopy(this.a, 0, a, 0, getMapSize());
+ }
+
+ public final void getRGBs(int rgb[])
+ {
+ if (this.argb == null) calcARGBArray();
+ System.arraycopy(this.argb, 0, rgb, 0, getMapSize());
+ }
+
+ public int getRed(int pixel)
+ {
+ try
+ {
+ return r[pixel];
+ }
+ catch (NullPointerException npe)
+ {
+ calcRGBArrays();
+ return r[pixel];
+ }
+ }
+
+ public int getGreen(int pixel)
+ {
+ try
+ {
+ return g[pixel];
+ }
+ catch (NullPointerException npe)
+ {
+ calcRGBArrays();
+ return g[pixel];
+ }
+ }
+
+ public int getBlue(int pixel)
+ {
+ try
+ {
+ return b[pixel];
+ }
+ catch (NullPointerException npe)
+ {
+ calcRGBArrays();
+ return b[pixel];
+ }
+ }
+
+ public int getAlpha(int pixel)
+ {
+ try
+ {
+ return a[pixel];
+ }
+ catch (NullPointerException npe)
+ {
+ calcAlphaArray();
+ return a[pixel];
+ }
+ }
+
+ private void calcRGBArrays() {
+ int j=0;
+ boolean hasAlpha = hasAlpha();
+ r = new byte[size];
+ g = new byte[size];
+ b = new byte[size];
+ if (hasAlpha) a = new byte[size];
+
+ for (int i=0; i<size; i++)
+ {
+ r[i] = cmap[j++];
+ g[i] = cmap[j++];
+ b[i] = cmap[j++];
+ if (hasAlpha()) a[i] = cmap[j++];
+ }
+ }
+
+ private void calcAlphaArray()
+ {
+ int transparency = getTransparency();
+ switch (transparency)
+ {
+ case Transparency.OPAQUE:
+ case Transparency.BITMASK:
+ a = nArray((byte) 255, size);
+ if (transparency == Transparency.BITMASK)
+ a[transparent] = 0;
+ break;
+ case Transparency.TRANSLUCENT:
+ calcRGBArrays();
+ }
+ }
+
+ private void calcARGBArray()
+ {
+ int mapSize = getMapSize();
+ argb = new int[mapSize];
+ for (int p=0; p<mapSize; p++) argb[p] = getRGB(p);
+ }
+
+ public int getRed(Object inData)
+ {
+ return getRed(getPixelFromArray(inData));
+ }
+
+ public int getGreen(Object inData)
+ {
+ return getGreen(getPixelFromArray(inData));
+ }
+
+ public int getBlue(Object inData)
+ {
+ return getBlue(getPixelFromArray(inData));
+ }
+
+ public int getAlpha(Object inData)
+ {
+ return getAlpha(getPixelFromArray(inData));
+ }
+
+ public int getRGB(Object inData)
+ {
+ return getRGB(getPixelFromArray(inData));
+ }
+
+ public Object getDataElements(int rgb, Object pixel)
+ {
+ int av, rv, gv, bv;
+ // using 8 bit values
+ av = (rgb >>> 24) & 0xff;
+ rv = (rgb >>> 16) & 0xff;
+ gv = (rgb >>> 8) & 0xff;
+ bv = (rgb >>> 0) & 0xff;
+
+ int pixelValue = getPixelValue(av, rv, gv, bv);
+
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ private int getPixelValue(int av, int rv, int gv, int bv)
+ {
+ if (r == null) calcRGBArrays();
+ if (a == null) calcAlphaArray();
+
+ int minDAlpha = 1<<8;
+ int minDRGB = (1<<8)*(1<<8)*3;
+ int pixelValue = -1;
+ for (int i=0; i<size; i++)
+ {
+ int dAlpha = Math.abs(av-(a[i]&0xff));
+ if (dAlpha > minDAlpha) continue;
+ int dR = rv-(r[i]&0xff);
+ int dG = gv-(g[i]&0xff);
+ int dB = bv-(b[i]&0xff);
+ int dRGB = dR*dR + dG*dG + dB*dB;
+
+ if (dRGB >= minDRGB) continue;
+
+ pixelValue = i;
+ minDRGB = dRGB;
+ }
+ return pixelValue;
+ }
+
+ public int[] getComponents(int pixel, int[] components, int offset)
+ {
+ int numComponents = getNumComponents();
+ if (components == null) components = new int[offset + numComponents];
+ components[offset++] = (r[pixel]&0xff);
+ components[offset++] = (g[pixel]&0xff);
+ components[offset++] = (b[pixel]&0xff);
+ if (hasAlpha()) components[offset++] = (a[pixel]&0xff);
+ return components;
+ }
+
+ public final int[] getComponents(Object pixel, int[] components,
+ int offset)
+ {
+ return getComponents(getPixelFromArray(pixel), components, offset);
+ }
+
+ public int getDataElement(int[] components, int offset)
+ {
+ int r = components[offset++];
+ int g = components[offset++];
+ int b = components[offset++];
+ int a = hasAlpha() ? components[offset++] : 255;
+
+ return getPixelValue(a, r, g, b);
+ }
+
+ public Object getDataElements(int[] components, int offset, Object pixel)
+ {
+ int pixelValue = getDataElement(components, offset);
+
+ /* In this color model, the whole pixel fits in the first element
+ of the array. */
+ DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
+ buffer.setElem(0, pixelValue);
+ return Buffers.getData(buffer);
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ int[] bandOffsets = {0};
+ return new ComponentSampleModel(transferType, w, h,
+ 1, // pixel stride
+ w, // scanline stride
+ bandOffsets);
+ }
+}
diff --git a/libjava/java/awt/image/PackedColorModel.java b/libjava/java/awt/image/PackedColorModel.java
new file mode 100644
index 0000000..a72ae2d
--- /dev/null
+++ b/libjava/java/awt/image/PackedColorModel.java
@@ -0,0 +1,162 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.color.ColorSpace;
+import gnu.gcj.awt.BitMaskExtent;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public abstract class PackedColorModel extends ColorModel
+{
+ private int masks[];
+
+ /* Package accessibility, the DirectColorModel needs this array */
+ int shifts[];
+
+ public PackedColorModel(ColorSpace cspace, int pixelBits,
+ int[] colorMaskArray, int alphaMask,
+ boolean isAlphaPremultiplied,
+ int transparency,
+ int transferType)
+ {
+ super(pixelBits, calcBitsPerComponent(colorMaskArray, alphaMask),
+ cspace, (alphaMask != 0), isAlphaPremultiplied, transparency,
+ transferType);
+ initMasks(colorMaskArray, alphaMask);
+ if ((pixelBits<1) || (pixelBits>32)) {
+ throw new IllegalArgumentException("pixels per bits must be " +
+ "in the range [1, 32]");
+ }
+ }
+
+ private static int[] calcBitsPerComponent(int[] colorMaskArray,
+ int alphaMask)
+ {
+ int numComponents = colorMaskArray.length;
+ if (alphaMask != 0) numComponents++;
+
+ int[] bitsPerComponent = new int[numComponents];
+
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<colorMaskArray.length; b++)
+ {
+ extent.setMask(colorMaskArray[b]);
+ bitsPerComponent[b] = extent.bitWidth;
+ }
+ if (alphaMask != 0)
+ {
+ extent.setMask(alphaMask);
+ bitsPerComponent[numComponents-1] = extent.bitWidth;
+ }
+ return bitsPerComponent;
+ }
+
+ /** Initializes the masks.
+ *
+ * @return an array containing the number of bits per color
+ * component.
+ */
+ private void initMasks(int[] colorMaskArray, int alphaMask)
+ {
+ int numComponents = colorMaskArray.length;
+ if (alphaMask == 0)
+ {
+ masks = colorMaskArray;
+ }
+ else
+ {
+ masks = new int[numComponents+1];
+ System.arraycopy(colorMaskArray, 0,
+ masks, 0,
+ numComponents);
+ masks[numComponents++] = alphaMask;
+ }
+
+ shifts = new int[numComponents];
+
+ // Bit field handling have been moved to a utility class
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<numComponents; b++)
+ {
+ extent.setMask(masks[b]);
+ shifts[b] = extent.leastSignificantBit;
+ }
+ }
+
+ public PackedColorModel(ColorSpace cspace, int pixelBits,
+ int rmask, int gmask, int bmask,
+ int amask, boolean isAlphaPremultiplied,
+ int transparency,
+ int transferType)
+ {
+ this(cspace, pixelBits, makeColorMaskArray(rmask, gmask, bmask),
+ amask, isAlphaPremultiplied, transparency, transferType);
+ }
+
+ /* TODO: If there is a alpha mask, it is inefficient to create a
+ color mask array that will be discarded when the alpha mask is
+ appended. We should probably create a private constructor that
+ takes a complete array of masks (color+alpha) as an
+ argument. */
+
+ private static int[] makeColorMaskArray(int rmask, int gmask, int bmask)
+ {
+ int[] colorMaskArray = { rmask, gmask, bmask };
+ return colorMaskArray;
+ }
+
+ public final int getMask(int index)
+ {
+ return masks[index];
+ }
+
+ public final int[] getMasks()
+ {
+ return masks;
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ return new SinglePixelPackedSampleModel(transferType, w, h, masks);
+ }
+
+ public boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ if (!super.isCompatibleSampleModel(sm)) return false;
+ if (!(sm instanceof SinglePixelPackedSampleModel)) return false;
+
+ SinglePixelPackedSampleModel sppsm =
+ (SinglePixelPackedSampleModel) sm;
+ return java.util.Arrays.equals(sppsm.getBitMasks(), masks);
+ }
+
+ public WritableRaster getAlphaRaster(WritableRaster raster) {
+ if (!hasAlpha()) return null;
+
+ SampleModel sm = raster.getSampleModel();
+ int[] alphaBand = { sm.getNumBands() - 1 };
+ SampleModel alphaModel = sm.createSubsetSampleModel(alphaBand);
+ DataBuffer buffer = raster.getDataBuffer();
+ Point origin = new Point(0, 0);
+ return Raster.createWritableRaster(alphaModel, buffer, origin);
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!super.equals(obj)) return false;
+ if (!(obj instanceof PackedColorModel)) return false;
+
+ PackedColorModel other = (PackedColorModel) obj;
+
+ return java.util.Arrays.equals(masks, other.masks);
+ }
+}
diff --git a/libjava/java/awt/image/Raster.java b/libjava/java/awt/image/Raster.java
new file mode 100644
index 0000000..46786d9
--- /dev/null
+++ b/libjava/java/awt/image/Raster.java
@@ -0,0 +1,418 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import java.awt.*;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class Raster
+{
+ protected SampleModel sampleModel;
+ protected DataBuffer dataBuffer;
+ protected int minX;
+ protected int minY;
+ protected int width;
+ protected int height;
+ protected int sampleModelTranslateX;
+ protected int sampleModelTranslateY;
+ protected int numBands;
+ protected int numDataElements;
+ protected Raster parent;
+
+ protected Raster(SampleModel sampleModel, Point origin)
+ {
+ this(sampleModel, sampleModel.createDataBuffer(), origin);
+ }
+
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Point origin)
+ {
+ this(sampleModel, dataBuffer,
+ new Rectangle(origin.x, origin.y,
+ sampleModel.getWidth(), sampleModel.getHeight()),
+ origin, null);
+ }
+
+ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate, Raster parent)
+ {
+ this.sampleModel = sampleModel;
+ this.dataBuffer = dataBuffer;
+ this.minX = aRegion.x;
+ this.minY = aRegion.y;
+ this.width = aRegion.width;
+ this.height = aRegion.height;
+ this.sampleModelTranslateX = sampleModelTranslate.x;
+ this.sampleModelTranslateY = sampleModelTranslate.y;
+ this.numBands = sampleModel.getNumBands();
+ this.numDataElements = sampleModel.getNumDataElements();
+ this.parent = parent;
+ }
+
+ public static WritableRaster createInterleavedRaster(int dataType,
+ int w, int h,
+ int bands,
+ Point location)
+ {
+ int[] bandOffsets = new int[bands];
+ // TODO: Maybe not generate this every time.
+ for (int b=0; b<bands; b++) bandOffsets[b] = b;
+
+ int scanlineStride = bands*w;
+ return createInterleavedRaster(dataType, w, h, scanlineStride, bands,
+ bandOffsets, location);
+ }
+
+ public static WritableRaster createInterleavedRaster(int dataType,
+ int w, int h,
+ int scanlineStride,
+ int pixelStride,
+ int[] bandOffsets,
+ Point location)
+ {
+ SampleModel sm = new ComponentSampleModel(dataType,
+ w, h,
+ pixelStride,
+ scanlineStride,
+ bandOffsets);
+ return createWritableRaster(sm, location);
+ }
+
+ public static WritableRaster createBandedRaster(int dataType,
+ int w, int h, int bands,
+ Point location)
+ {
+ // FIXME: Implement;
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+ public static WritableRaster createBandedRaster(int dataType,
+ int w, int h,
+ int scanlineStride,
+ int[] bankIndices,
+ int[] bandOffsets,
+ Point location)
+ {
+ // FIXME: Implement;
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+ public static WritableRaster createPackedRaster(int dataType,
+ int w, int h,
+ int[] bandMasks,
+ Point location)
+ {
+ SampleModel sm = new SinglePixelPackedSampleModel(dataType,
+ w, h,
+ bandMasks);
+ return createWritableRaster(sm, location);
+ }
+
+ public static WritableRaster
+ createInterleavedRaster(DataBuffer dataBuffer, int w, int h,
+ int scanlineStride, int pixelStride,
+ int[] bandOffsets, Point location)
+ {
+ SampleModel sm = new ComponentSampleModel(dataBuffer.getDataType(),
+ w, h,
+ scanlineStride,
+ pixelStride,
+ bandOffsets);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ public static
+ WritableRaster createBandedRaster(DataBuffer dataBuffer,
+ int w, int h,
+ int scanlineStride,
+ int[] bankIndices,
+ int[] bandOffsets,
+ Point location)
+ {
+ // FIXME: Implement;
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+ public static WritableRaster
+ createPackedRaster(DataBuffer dataBuffer,
+ int w, int h,
+ int scanlineStride,
+ int[] bandMasks,
+ Point location) {
+ SampleModel sm =
+ new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
+ w, h,
+ scanlineStride,
+ bandMasks);
+ return createWritableRaster(sm, dataBuffer, location);
+ }
+
+ public static Raster createRaster(SampleModel sm, DataBuffer db,
+ Point location)
+ {
+ return new Raster(sm, db, location);
+ }
+
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ Point location)
+ {
+ return new WritableRaster(sm, location);
+ }
+
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ DataBuffer db,
+ Point location)
+ {
+ return new WritableRaster(sm, db, location);
+ }
+
+ public Raster getParent()
+ {
+ return parent;
+ }
+
+ public final int getSampleModelTranslateX()
+ {
+ return sampleModelTranslateX;
+ }
+
+ public final int getSampleModelTranslateY()
+ {
+ return sampleModelTranslateY;
+ }
+
+ public WritableRaster createCompatibleWritableRaster()
+ {
+ return new WritableRaster(getSampleModel(), new Point(minX, minY));
+ }
+
+ public WritableRaster createCompatibleWritableRaster(int w, int h)
+ {
+ return createCompatibleWritableRaster(minX, minY, w, h);
+ }
+
+ public WritableRaster createCompatibleWritableRaster(Rectangle rect)
+ {
+ return createCompatibleWritableRaster(rect.x, rect.y,
+ rect.width, rect.height);
+ }
+
+ public WritableRaster createCompatibleWritableRaster(int x, int y,
+ int w, int h)
+ {
+ SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h);
+ return new WritableRaster(sm, sm.createDataBuffer(),
+ new Point(x, y));
+ }
+
+ public Raster createTranslatedChild(int childMinX, int childMinY) {
+ int tcx = sampleModelTranslateX - minX + childMinX;
+ int tcy = sampleModelTranslateY - minY + childMinY;
+
+ return new Raster(sampleModel, dataBuffer,
+ new Rectangle(childMinX, childMinY,
+ width, height),
+ new Point(tcx, tcy),
+ this);
+ }
+
+ public Raster createChild(int parentX, int parentY, int width,
+ int height, int childMinX, int childMinY,
+ int[] bandList)
+ {
+ /* FIXME: Throw RasterFormatException if child bounds extends
+ beyond the bounds of this raster. */
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ /*
+ data origin
+ /
+ +-------------------------
+ |\. __ parent trans
+ | \`.
+ | \ `. parent origin
+ | \ `. /
+ | /\ +-------- - -
+ |trans\ /<\-- deltaTrans
+ |child +-+-\---- - -
+ | /|`| \__ parent [x, y]
+ |child | |`. \
+ |origin| : `.\
+ | | / `\
+ | : / +
+ | child [x, y]
+
+ parent_xy - parent_trans = child_xy - child_trans
+
+ child_trans = parent_trans + child_xy - parent_xy
+ */
+
+ return new Raster(sm, dataBuffer,
+ new Rectangle(childMinX, childMinY,
+ width, height),
+ new Point(sampleModelTranslateX+childMinX-parentX,
+ sampleModelTranslateY+childMinY-parentY),
+ this);
+ }
+
+ public Rectangle getBounds()
+ {
+ return new Rectangle(minX, minY, width, height);
+ }
+
+ public final int getMinX()
+ {
+ return minX;
+ }
+
+ public final int getMinY()
+ {
+ return minY;
+ }
+
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ public final int getNumDataElements()
+ {
+ return numDataElements;
+ }
+
+ public final int getTransferType()
+ {
+ return sampleModel.getTransferType();
+ }
+
+ public DataBuffer getDataBuffer()
+ {
+ return dataBuffer;
+ }
+
+ public SampleModel getSampleModel()
+ {
+ return sampleModel;
+ }
+
+ public Object getDataElements(int x, int y, Object outData)
+ {
+ return sampleModel.getDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ outData, dataBuffer);
+ }
+
+ public Object getDataElements(int x, int y, int w, int h,
+ Object outData)
+ {
+ return sampleModel.getDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, outData, dataBuffer);
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray)
+ {
+ return sampleModel.getPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ iArray, dataBuffer);
+ }
+
+ public float[] getPixel(int x, int y, float[] fArray)
+ {
+ return sampleModel.getPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ fArray, dataBuffer);
+ }
+
+ public double[] getPixel(int x, int y, double[] dArray)
+ {
+ return sampleModel.getPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ dArray, dataBuffer);
+ }
+
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray)
+ {
+ return sampleModel.getPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, iArray, dataBuffer);
+ }
+
+ public float[] getPixels(int x, int y, int w, int h,
+ float[] fArray)
+ {
+ return sampleModel.getPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, fArray, dataBuffer);
+ }
+
+ public double[] getPixels(int x, int y, int w, int h,
+ double[] dArray)
+ {
+ return sampleModel.getPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, dArray, dataBuffer);
+ }
+
+ public int getSample(int x, int y, int b)
+ {
+ return sampleModel.getSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, dataBuffer);
+ }
+
+ public float getSampleFloat(int x, int y, int b)
+ {
+ return sampleModel.getSampleFloat(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, dataBuffer);
+ }
+
+ public double getSampleDouble(int x, int y, int b)
+ {
+ return sampleModel.getSampleDouble(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, dataBuffer);
+ }
+
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int[] iArray)
+ {
+ return sampleModel.getSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, iArray, dataBuffer);
+ }
+
+ public float[] getSamples(int x, int y, int w, int h, int b,
+ float[] fArray)
+ {
+ return sampleModel.getSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, fArray, dataBuffer);
+ }
+
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double[] dArray)
+ {
+ return sampleModel.getSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, dArray, dataBuffer);
+ }
+}
diff --git a/libjava/java/awt/image/SampleModel.java b/libjava/java/awt/image/SampleModel.java
new file mode 100644
index 0000000..3368c83
--- /dev/null
+++ b/libjava/java/awt/image/SampleModel.java
@@ -0,0 +1,436 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public abstract class SampleModel
+{
+ /** Width of image described. */
+ protected int width;
+
+ /** Height of image described. */
+ protected int height;
+
+ /** Number of bands in the image described. */
+ protected int numBands;
+
+ /**
+ * The DataBuffer type that is used to store the data of the image
+ * described.
+ */
+ protected int dataType;
+
+ public SampleModel(int dataType, int w, int h, int numBands)
+ {
+ if ((w<=0) || (h<=0)) throw new IllegalArgumentException();
+
+ // FIXME: How can an int be greater than Integer.MAX_VALUE?
+ // FIXME: How do we identify an unsupported data type?
+
+ this.dataType = dataType;
+ this.width = w;
+ this.height = h;
+ this.numBands = numBands;
+ }
+
+ public final int getWidth()
+ {
+ return width;
+ }
+
+ public final int getHeight()
+ {
+ return height;
+ }
+
+ public final int getNumBands()
+ {
+ return numBands;
+ }
+
+ public abstract int getNumDataElements();
+
+ public final int getDataType()
+ {
+ return dataType;
+ }
+
+ public int getTransferType()
+ {
+ // FIXME: Is this a reasonable default implementation?
+ return dataType;
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ if (iArray == null) iArray = new int[numBands];
+ for (int b=0; b<numBands; b++) iArray[b] = getSample(x, y, b, data);
+ return iArray;
+ }
+
+ /**
+ *
+ * This method is provided as a faster alternative to getPixel(),
+ * that can be used when there is no need to decode the pixel into
+ * seperate sample values.
+ *
+ * @param obj An array to return the pixel data in. If null, an
+ * array of the right type and size will be created.
+ *
+ * @return A single pixel as an array object of a primitive type,
+ * based on the transfer type. Eg. if transfer type is
+ * DataBuffer.TYPE_USHORT, then a short[] object is returned.
+ */
+ public abstract Object getDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+
+ public Object getDataElements(int x, int y, int w, int h, Object obj,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int numDataElements = getNumDataElements();
+ int dataSize = numDataElements*size;
+
+ if (obj == null)
+ {
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ obj = new byte[dataSize];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ obj = new short[dataSize];
+ break;
+ case DataBuffer.TYPE_INT:
+ obj = new int[dataSize];
+ break;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ }
+ Object pixelData = null;
+ int outOffset = 0;
+ for (int yy = y; yy<(y+h); yy++)
+ {
+ for (int xx = x; xx<(x+w); xx++)
+ {
+ pixelData = getDataElements(xx, yy, pixelData, data);
+ System.arraycopy(pixelData, 0, obj, outOffset,
+ numDataElements);
+ outOffset += numDataElements;
+ }
+ }
+ return obj;
+ }
+
+ public abstract void setDataElements(int x, int y, Object obj,
+ DataBuffer data);
+
+ public void setDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data)
+ {
+ int size = w*h;
+ int numDataElements = getNumDataElements();
+ int dataSize = numDataElements*size;
+
+ Object pixelData;
+ switch (getTransferType())
+ {
+ case DataBuffer.TYPE_BYTE:
+ pixelData = new byte[numDataElements];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ pixelData = new short[numDataElements];
+ break;
+ case DataBuffer.TYPE_INT:
+ pixelData = new int[numDataElements];
+ break;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
+ int inOffset = 0;
+
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(obj, inOffset, pixelData, 0,
+ numDataElements);
+ setDataElements(xx, yy, pixelData, data);
+ inOffset += numDataElements;
+ }
+ }
+ }
+
+ public float[] getPixel(int x, int y, float[] fArray, DataBuffer data)
+ {
+ if (fArray == null) fArray = new float[numBands];
+
+ for (int b=0; b<numBands; b++)
+ {
+ fArray[0] = getSampleFloat(x, y, b, data);
+ }
+ return fArray;
+ }
+
+ public double[] getPixel(int x, int y, double[] dArray, DataBuffer data) {
+ if (dArray == null) dArray = new double[numBands];
+ for (int b=0; b<numBands; b++)
+ {
+ dArray[0] = getSampleDouble(x, y, b, data);
+ }
+ return dArray;
+ }
+
+ /* FIXME: Should it return a banded or pixel interleaved array of
+ samples? (Assume interleaved.) */
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ int[] pixel = null;
+ if (iArray == null) iArray = new int[w*h*numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, iArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return iArray;
+ }
+
+ /* FIXME: Should it return a banded or pixel interleaved array of
+ samples? (Assume interleaved.) */
+ public float[] getPixels(int x, int y, int w, int h, float[] fArray,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ float[] pixel = null;
+ if (fArray == null) fArray = new float[w*h*numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, fArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return fArray;
+ }
+
+ /* FIXME: Should it return a banded or pixel interleaved array of
+ samples? (Assume interleaved.) */
+ public double[] getPixels(int x, int y, int w, int h, double[] dArray,
+ DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ double[] pixel = null;
+ if (dArray == null) dArray = new double[w*h*numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ getPixel(xx, yy, pixel, data);
+ System.arraycopy(pixel, 0, dArray, outOffset, numBands);
+ outOffset += numBands;
+ }
+ }
+ return dArray;
+ }
+
+ public abstract int getSample(int x, int y, int b, DataBuffer data);
+
+ public float getSampleFloat(int x, int y, int b, DataBuffer data)
+ {
+ return getSample(x, y, b, data);
+ }
+
+ public double getSampleDouble(int x, int y, int b, DataBuffer data)
+ {
+ return getSampleFloat(x, y, b, data);
+ }
+
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int[] iArray, DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ if (iArray == null) iArray = new int[size];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ iArray[outOffset++] = getSample(xx, yy, b, data);
+ }
+ }
+ return iArray;
+ }
+
+ public float[] getSamples(int x, int y, int w, int h, int b,
+ float[] fArray, DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ if (fArray == null) fArray = new float[size];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ fArray[outOffset++] = getSampleFloat(xx, yy, b, data);
+ }
+ }
+ return fArray;
+ }
+
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double[] dArray, DataBuffer data)
+ {
+ int size = w*h;
+ int outOffset = 0;
+ if (dArray == null) dArray = new double[size];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ dArray[outOffset++] = getSampleDouble(xx, yy, b, data);
+ }
+ }
+ return dArray;
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ for (int b=0; b<numBands; b++) setSample(x, y, b, iArray[b], data);
+ }
+
+ public void setPixel(int x, int y, float[] fArray, DataBuffer data)
+ {
+ for (int b=0; b<numBands; b++) setSample(x, y, b, fArray[b], data);
+ }
+
+ public void setPixel(int x, int y, double[] dArray, DataBuffer data)
+ {
+ for (int b=0; b<numBands; b++) setSample(x, y, b, dArray[b], data);
+ }
+
+ public void setPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ int[] pixel = new int[numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(iArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ public void setPixels(int x, int y, int w, int h, float[] fArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ float[] pixel = new float[numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(fArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ public void setPixels(int x, int y, int w, int h, double[] dArray,
+ DataBuffer data)
+ {
+ int inOffset = 0;
+ double[] pixel = new double[numBands];
+ for (int yy=y; yy<(y+h); yy++)
+ {
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(dArray, inOffset, pixel, 0, numBands);
+ setPixel(xx, yy, pixel, data);
+ inOffset += numBands;
+ }
+ }
+ }
+
+ public abstract void setSample(int x, int y, int b, int s,
+ DataBuffer data);
+
+ public void setSample(int x, int y, int b, float s,
+ DataBuffer data)
+ {
+ setSample(x, y, b, (int) s, data);
+ }
+
+ public void setSample(int x, int y, int b, double s,
+ DataBuffer data)
+ {
+ setSample(x, y, b, (float) s, data);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ int[] iArray, DataBuffer data)
+ {
+ int size = w*h;
+ int inOffset = 0;
+ for (int yy=y; yy<(y+h); yy++)
+ for (int xx=x; xx<(x+w); xx++)
+ setSample(xx, yy, b, iArray[inOffset++], data);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ float[] fArray, DataBuffer data)
+ {
+ int size = w*h;
+ int inOffset = 0;
+ for (int yy=y; yy<(y+h); yy++)
+ for (int xx=x; xx<(x+w); xx++)
+ setSample(xx, yy, b, fArray[inOffset++], data);
+
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ double[] dArray, DataBuffer data) {
+ int size = w*h;
+ int inOffset = 0;
+ for (int yy=y; yy<(y+h); yy++)
+ for (int xx=x; xx<(x+w); xx++)
+ setSample(xx, yy, b, dArray[inOffset++], data);
+ }
+
+ public abstract SampleModel createCompatibleSampleModel(int w, int h);
+
+ public abstract SampleModel createSubsetSampleModel(int[] bands);
+
+ public abstract DataBuffer createDataBuffer();
+
+ public abstract int[] getSampleSize();
+
+ public abstract int getSampleSize(int band);
+}
diff --git a/libjava/java/awt/image/SinglePixelPackedSampleModel.java b/libjava/java/awt/image/SinglePixelPackedSampleModel.java
new file mode 100644
index 0000000..3baea04
--- /dev/null
+++ b/libjava/java/awt/image/SinglePixelPackedSampleModel.java
@@ -0,0 +1,245 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import gnu.gcj.awt.BitMaskExtent;
+import gnu.gcj.awt.Buffers;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class SinglePixelPackedSampleModel extends SampleModel
+{
+ private int scanlineStride;
+ private int[] bitMasks;
+ private int[] bitOffsets;
+ private int[] sampleSize;;
+
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int[] bitMasks)
+ {
+ this(dataType, w, h, w, bitMasks);
+ }
+
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int scanlineStride, int[] bitMasks)
+ {
+ super(dataType, w, h, bitMasks.length);
+
+ this.scanlineStride = scanlineStride;
+ this.bitMasks = bitMasks;
+
+ bitOffsets = new int[numBands];
+ sampleSize = new int[numBands];
+
+ BitMaskExtent extent = new BitMaskExtent();
+ for (int b=0; b<numBands; b++)
+ {
+ extent.setMask(bitMasks[b]);
+ sampleSize[b] = extent.bitWidth;
+ bitOffsets[b] = extent.leastSignificantBit;
+ }
+ }
+
+ public int getNumDataElements()
+ {
+ return 1;
+ }
+
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ /* FIXME: We can avoid recalculation of bit offsets and sample
+ sizes here by passing these from the current instance to a
+ special private constructor. */
+ return new SinglePixelPackedSampleModel(dataType, w, h, bitMasks);
+ }
+
+ public DataBuffer createDataBuffer()
+ {
+ // Important: use scanlineStride here, not width!
+ int size = scanlineStride*height;
+ return Buffers.createBuffer(getDataType(), size);
+ }
+
+ public int[] getSampleSize()
+ {
+ return sampleSize;
+ }
+
+ public int getSampleSize(int band)
+ {
+ return sampleSize[band];
+ }
+
+ public int getOffset(int x, int y)
+ {
+ return scanlineStride*y + x;
+ }
+
+ public int[] getBitOffsets()
+ {
+ return bitOffsets;
+ }
+
+ public int[] getBitMasks()
+ {
+ return bitMasks;
+ }
+
+ public int getScanlineStride()
+ {
+ return scanlineStride;
+ }
+
+ public SampleModel createSubsetSampleModel(int[] bands)
+ {
+ // FIXME: Is this the right way to interpret bands?
+
+ int numBands = bands.length;
+
+ int[] bitMasks = new int[numBands];
+
+ for (int b=0; b<numBands; b++)
+ bitMasks[b] = this.bitMasks[bands[b]];
+
+ return new SinglePixelPackedSampleModel(dataType, width, height,
+ scanlineStride, bitMasks);
+ }
+
+ public Object getDataElements(int x, int y, Object obj,
+ DataBuffer data)
+ {
+ int offset = scanlineStride*y + x + data.getOffset();
+
+ return Buffers.getData(data, offset, obj,
+ 0, // destination offset,
+ 1 // length
+ );
+ }
+
+ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ if (iArray == null) iArray = new int[numBands];
+ int samples = data.getElem(offset);
+
+ for (int b=0; b<numBands; b++)
+ iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
+
+ return iArray;
+ }
+
+ public int[] getPixels(int x, int y, int w, int h, int[] iArray,
+ DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ if (iArray == null) iArray = new int[numBands*w*h];
+ int outOffset = 0;
+ for (y=0; y<h; y++)
+ {
+ int lineOffset = offset;
+ for (x=0; x<w; x++)
+ {
+ int samples = data.getElem(lineOffset++);
+ for (int b=0; b<numBands; b++)
+ iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
+ }
+ offset += scanlineStride;
+ }
+ return iArray;
+ }
+
+ public int getSample(int x, int y, int b, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ int samples = data.getElem(offset);
+ return (samples & bitMasks[b]) >>> bitOffsets[b];
+ }
+
+ public void setDataElements(int x, int y, Object obj, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x + data.getOffset();
+
+ int transferType = getTransferType();
+ if (getTransferType() != data.getDataType())
+ {
+ throw new IllegalArgumentException("transfer type ("+
+ getTransferType()+"), "+
+ "does not match data "+
+ "buffer type (" +
+ data.getDataType() +
+ ").");
+ }
+
+ try
+ {
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ DataBufferByte out = (DataBufferByte) data;
+ byte[] in = (byte[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ DataBufferUShort out = (DataBufferUShort) data;
+ short[] in = (short[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ DataBufferInt out = (DataBufferInt) data;
+ int[] in = (int[]) obj;
+ out.getData()[offset] = in[0];
+ return;
+ }
+ // FIXME: Fill in the other possible types.
+ default:
+ throw new InternalError();
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException aioobe)
+ {
+ String msg = "While writing data elements" +
+ ", x="+x+", y="+y+
+ ", width="+width+", height="+height+
+ ", scanlineStride="+scanlineStride+
+ ", offset="+offset+
+ ", data.getSize()="+data.getSize()+
+ ", data.getOffset()="+data.getOffset()+
+ ": " +
+ aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
+ }
+ }
+
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+
+ int samples = 0;
+ for (int b=0; b<numBands; b++)
+ samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];
+
+ data.setElem(offset, samples);
+ }
+
+ public void setSample(int x, int y, int b, int s, DataBuffer data)
+ {
+ int offset = scanlineStride*y + x;
+ int samples = data.getElem(offset);
+ int bitMask = bitMasks[b];
+ samples &= ~bitMask;
+ samples |= (s << bitOffsets[b]) & bitMask;
+ data.setElem(offset, samples);
+ }
+}
diff --git a/libjava/java/awt/image/WritableRaster.java b/libjava/java/awt/image/WritableRaster.java
new file mode 100644
index 0000000..6667256
--- /dev/null
+++ b/libjava/java/awt/image/WritableRaster.java
@@ -0,0 +1,234 @@
+/* Copyright © 2000 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.awt.image;
+
+import java.awt.*;
+
+/**
+ * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
+ */
+public class WritableRaster extends Raster
+{
+ protected WritableRaster(SampleModel sampleModel, Point origin)
+ {
+ this(sampleModel, sampleModel.createDataBuffer(), origin);
+ }
+
+ protected WritableRaster(SampleModel sampleModel,
+ DataBuffer dataBuffer, Point origin)
+ {
+ this(sampleModel, dataBuffer,
+ new Rectangle(origin.x, origin.y,
+ sampleModel.getWidth(), sampleModel.getHeight()),
+ origin,
+ null);
+ }
+
+ protected WritableRaster(SampleModel sampleModel,
+ DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate,
+ WritableRaster parent)
+ {
+ super(sampleModel, dataBuffer, aRegion, sampleModelTranslate,
+ parent);
+ }
+
+ public WritableRaster getWritableParent()
+ {
+ return (WritableRaster) getParent();
+ }
+
+ public WritableRaster createWritableTranslatedChild(int childMinX,
+ int childMinY)
+ {
+ // This mirrors the code from the super class
+ int tcx = sampleModelTranslateX - minX + childMinX;
+ int tcy = sampleModelTranslateY - minY + childMinY;
+
+ return new WritableRaster(sampleModel, dataBuffer,
+ new Rectangle(childMinX, childMinY,
+ width, height),
+ new Point(tcx, tcy),
+ this);
+ }
+
+ public WritableRaster createWritableChild(int parentX,
+ int parentY,
+ int w, int h,
+ int childMinX,
+ int childMinY,
+ int[] bandList)
+ {
+ // This mirrors the code from the super class
+
+ // FIXME: Throw RasterFormatException if child bounds extends
+ // beyond the bounds of this raster.
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ return new
+ WritableRaster(sm, dataBuffer,
+ new Rectangle(childMinX, childMinY,
+ w, h),
+ new Point(sampleModelTranslateX+childMinX-parentX,
+ sampleModelTranslateY+childMinY-parentY),
+ this);
+ }
+
+ public void setDataElements(int x, int y, Object inData)
+ {
+ sampleModel.setDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ inData, dataBuffer);
+ }
+
+ public void setDataElements(int x, int y, Raster inRaster)
+ {
+ Object dataElements = getDataElements(0, 0,
+ inRaster.getWidth(),
+ inRaster.getHeight(),
+ null);
+ setDataElements(x, y, dataElements);
+ }
+
+ public void setDataElements(int x, int y, int w, int h,
+ Object inData)
+ {
+ sampleModel.setDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, inData, dataBuffer);
+ }
+
+ public void setRect(Raster srcRaster)
+ {
+ setRect(srcRaster, 0, 0);
+ }
+
+ public void setRect(Raster srcRaster, int dx, int dy)
+ {
+ Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX()+dx,
+ srcRaster.getMinY()+dy,
+ srcRaster.getWidth(),
+ srcRaster.getHeight());
+
+ Rectangle target = getBounds().intersection(targetUnclipped);
+
+ if (target.isEmpty()) return;
+
+ int sx = target.x - dx;
+ int sy = target.y - dy;
+
+ // FIXME: Do tests on rasters and use get/set data instead.
+
+ /* The JDK documentation seems to imply this implementation.
+ (the trucation of higher bits), but an implementation using
+ get/setDataElements would be more efficient. None of the
+ implementations would do anything sensible when the sample
+ models don't match.
+
+ But this is probably not the place to consider such
+ optimizations.*/
+
+ int[] pixels = srcRaster.getPixels(sx, sy,
+ target.width, target.height,
+ (int[]) null);
+
+ setPixels(target.x, target.y, target.width, target.height, pixels);
+ }
+
+ public void setPixel(int x, int y, int[] iArray)
+ {
+ sampleModel.setPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ iArray, dataBuffer);
+ }
+
+ public void setPixel(int x, int y, float[] fArray)
+ {
+ sampleModel.setPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ fArray, dataBuffer);
+ }
+
+ public void setPixel(int x, int y, double[] dArray)
+ {
+ sampleModel.setPixel(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ dArray, dataBuffer);
+ }
+
+ public void setPixels(int x, int y, int w, int h, int[] iArray)
+ {
+ sampleModel.setPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, iArray, dataBuffer);
+ }
+
+ public void setPixels(int x, int y, int w, int h, float[] fArray)
+ {
+ sampleModel.setPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, fArray, dataBuffer);
+ }
+
+ public void setPixels(int x, int y, int w, int h, double[] dArray)
+ {
+ sampleModel.setPixels(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, dArray, dataBuffer);
+ }
+
+ public void setSample(int x, int y, int b, int s)
+ {
+ sampleModel.setSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ public void setSample(int x, int y, int b, float s)
+ {
+ sampleModel.setSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ public void setSample(int x, int y, int b, double s)
+ {
+ sampleModel.setSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ b, s, dataBuffer);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ int[] iArray)
+ {
+ sampleModel.setSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, iArray, dataBuffer);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ float[] fArray)
+ {
+ sampleModel.setSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, fArray, dataBuffer);
+ }
+
+ public void setSamples(int x, int y, int w, int h, int b,
+ double[] dArray)
+ {
+ sampleModel.setSamples(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w, h, b, dArray, dataBuffer);
+ }
+}