ColorModel.java: New file...
authorRolf W. Rasmussen <rolfwr@ii.uib.no>
Tue, 25 Jul 2000 17:53:30 +0000 (19:53 +0200)
committerRolf Rasmussen <rolfwr@gcc.gnu.org>
Tue, 25 Jul 2000 17:53:30 +0000 (17:53 +0000)
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

24 files changed:
libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/gnu/gcj/awt/BitMaskExtent.java [new file with mode: 0644]
libjava/gnu/gcj/awt/Buffers.java [new file with mode: 0644]
libjava/java/awt/ColorModel.java [deleted file]
libjava/java/awt/color/ColorSpace.java [new file with mode: 0644]
libjava/java/awt/color/ICC_ColorSpace.java [new file with mode: 0644]
libjava/java/awt/color/ICC_Profile.java [new file with mode: 0644]
libjava/java/awt/image/ColorModel.java [new file with mode: 0644]
libjava/java/awt/image/ComponentColorModel.java [new file with mode: 0644]
libjava/java/awt/image/ComponentSampleModel.java [new file with mode: 0644]
libjava/java/awt/image/DataBuffer.java [new file with mode: 0644]
libjava/java/awt/image/DataBufferByte.java [new file with mode: 0644]
libjava/java/awt/image/DataBufferInt.java [new file with mode: 0644]
libjava/java/awt/image/DataBufferUShort.java [new file with mode: 0644]
libjava/java/awt/image/DirectColorModel.java [new file with mode: 0644]
libjava/java/awt/image/ImageConsumer.java
libjava/java/awt/image/IndexColorModel.java [new file with mode: 0644]
libjava/java/awt/image/PackedColorModel.java [new file with mode: 0644]
libjava/java/awt/image/Raster.java [new file with mode: 0644]
libjava/java/awt/image/SampleModel.java [new file with mode: 0644]
libjava/java/awt/image/SinglePixelPackedSampleModel.java [new file with mode: 0644]
libjava/java/awt/image/WritableRaster.java [new file with mode: 0644]

index 655081fc143228fd0d14dcfe00d5d4daf3050b55..08dd834c91c46466358bf0880b7c35a3759b669f 100644 (file)
@@ -1,3 +1,30 @@
+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.
+
 2000-07-23  Oskar Liljeblad <osk@hem.passagen.se>
 
        * java/io/StreamTokenizer.java: Merged with classpath.
index b3ed536a49f9ecec0fbb70e6811a92b695055892..e558e1fcd2ffaeae5ba791f1fdda1338fdf4635e 100644 (file)
@@ -486,6 +486,8 @@ gnu/gcj/convert/UnicodeToBytes.java
 special_java_source_files = java/lang/Class.java java/lang/Object.java
 
 awt_java_source_files =        \
+gnu/gcj/awt/BitMaskExtent.java \
+gnu/gcj/awt/Buffers.java \
 java/awt/AWTError.java \
 java/awt/AWTEvent.java \
 java/awt/AWTEventMulticaster.java \
@@ -495,7 +497,6 @@ java/awt/Adjustable.java \
 java/awt/BorderLayout.java \
 java/awt/CheckboxGroup.java \
 java/awt/Color.java \
-java/awt/ColorModel.java \
 java/awt/Component.java        \
 java/awt/ComponentOrientation.java \
 java/awt/Container.java        \
@@ -535,6 +536,9 @@ java/awt/TextComponent.java \
 java/awt/Toolkit.java \
 java/awt/Transparency.java \
 java/awt/Window.java \
+java/awt/color/ColorSpace.java \
+java/awt/color/ICC_ColorSpace.java \
+java/awt/color/ICC_Profile.java \
 java/awt/event/AWTEventListener.java \
 java/awt/event/ActionEvent.java        \
 java/awt/event/ActionListener.java \
@@ -582,9 +586,23 @@ java/awt/geom/PathIterator.java    \
 java/awt/geom/Point2D.java \
 java/awt/geom/Rectangle2D.java \
 java/awt/geom/RectangularShape.java \
+java/awt/image/ColorModel.java \
+java/awt/image/ComponentColorModel.java \
+java/awt/image/ComponentSampleModel.java \
+java/awt/image/DataBuffer.java \
+java/awt/image/DataBufferByte.java \
+java/awt/image/DataBufferInt.java \
+java/awt/image/DataBufferUShort.java \
+java/awt/image/DirectColorModel.java \
 java/awt/image/ImageConsumer.java \
 java/awt/image/ImageObserver.java \
 java/awt/image/ImageProducer.java \
+java/awt/image/IndexColorModel.java \
+java/awt/image/PackedColorModel.java \
+java/awt/image/Raster.java \
+java/awt/image/SampleModel.java \
+java/awt/image/SinglePixelPackedSampleModel.java \
+java/awt/image/WritableRaster.java \
 java/awt/peer/ButtonPeer.java \
 java/awt/peer/CanvasPeer.java \
 java/awt/peer/CheckboxMenuItemPeer.java        \
index a3cc91f8670f99d6ece2f1cabc3be0137b46abaf..87ceae1a44becca33c00c573ec332b9aaf9dcd7d 100644 (file)
@@ -115,48 +115,31 @@ here = @here@
 libgcj_basedir = @libgcj_basedir@
 
 AUTOMAKE_OPTIONS = foreign no-installinfo
-@TESTSUBDIR_TRUE@SUBDIRS = \
-@TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
-@TESTSUBDIR_FALSE@SUBDIRS = \
-@TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
-@USE_LIBDIR_TRUE@toolexeclibdir = \
-@USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
-@USE_LIBDIR_FALSE@toolexeclibdir = \
-@USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
-@USE_LIBDIR_FALSE@toolexecdir = \
-@USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
+@TESTSUBDIR_TRUE@SUBDIRS = @TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
+@TESTSUBDIR_FALSE@SUBDIRS = @TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
+@USE_LIBDIR_TRUE@toolexeclibdir = @USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
+@USE_LIBDIR_FALSE@toolexeclibdir = @USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
+@USE_LIBDIR_FALSE@toolexecdir = @USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
 
 toolexeclib_LTLIBRARIES = libgcj.la
 toolexeclib_DATA = libgcj.spec
 data_DATA = libgcj.zip
 
-@NEEDS_DATA_START_TRUE@toolexeclib_LIBRARIES = \
-@NEEDS_DATA_START_TRUE@libgcjdata.a
-@NEEDS_DATA_START_TRUE@libgcjdata_a_SOURCES = \
-@NEEDS_DATA_START_TRUE@libgcjdata.c
+@NEEDS_DATA_START_TRUE@toolexeclib_LIBRARIES = @NEEDS_DATA_START_TRUE@libgcjdata.a
+@NEEDS_DATA_START_TRUE@libgcjdata_a_SOURCES = @NEEDS_DATA_START_TRUE@libgcjdata.c
 
-@NATIVE_TRUE@bin_PROGRAMS = \
-@NATIVE_TRUE@jv-convert gij
+@NATIVE_TRUE@bin_PROGRAMS = @NATIVE_TRUE@jv-convert gij
 
 bin_SCRIPTS = addr2name.awk
-@CANADIAN_TRUE@@NULL_TARGET_TRUE@GCJ = \
-@CANADIAN_TRUE@@NULL_TARGET_TRUE@gcj
-@CANADIAN_TRUE@@NULL_TARGET_FALSE@GCJ = \
-@CANADIAN_TRUE@@NULL_TARGET_FALSE@$(target_alias)-gcj
-@CANADIAN_FALSE@GCJ = \
-@CANADIAN_FALSE@$(expanded)/gcj$(EXEEXT) -B$(expanded)/
-@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = \
-@CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/zip/zip$(EXEEXT)
-@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = \
-@CANADIAN_TRUE@@NULL_TARGET_FALSE@zip
-@CANADIAN_FALSE@ZIP = \
-@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/zip/zip$(EXEEXT)
-@CANADIAN_TRUE@GCJH = \
-@CANADIAN_TRUE@gcjh
-@CANADIAN_FALSE@GCJH = \
-@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
-@CANADIAN_FALSE@expanded = \
-@CANADIAN_FALSE@`cd $(MULTIBUILDTOP)../$(COMPPATH)/gcc && pwd`
+@CANADIAN_TRUE@@NULL_TARGET_TRUE@GCJ = @CANADIAN_TRUE@@NULL_TARGET_TRUE@gcj
+@CANADIAN_TRUE@@NULL_TARGET_FALSE@GCJ = @CANADIAN_TRUE@@NULL_TARGET_FALSE@$(target_alias)-gcj
+@CANADIAN_FALSE@GCJ = @CANADIAN_FALSE@$(expanded)/gcj$(EXEEXT) -B$(expanded)/
+@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/zip/zip$(EXEEXT)
+@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_FALSE@zip
+@CANADIAN_FALSE@ZIP = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/zip/zip$(EXEEXT)
+@CANADIAN_TRUE@GCJH = @CANADIAN_TRUE@gcjh
+@CANADIAN_FALSE@GCJH = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
+@CANADIAN_FALSE@expanded = @CANADIAN_FALSE@`cd $(MULTIBUILDTOP)../$(COMPPATH)/gcc && pwd`
 
 GCJCOMPILE = CLASSPATH=$(here) $(LIBTOOL) --mode=compile $(GCJ) -fassume-compiled -L$(here) $(JC1FLAGS) -c
 GCJLINK = $(LIBTOOL) --mode=link $(GCJ) -L$(here) $(JC1FLAGS) $(LDFLAGS) -o $@
@@ -170,10 +153,8 @@ WARNINGS = -W -Wall
 AM_CXXFLAGS = -fno-rtti -fvtable-thunks -fasynchronous-exceptions \
        @LIBGCJ_CXXFLAGS@ @EXCEPTIONSPEC@ $(WARNINGS) -D_GNU_SOURCE
 
-@USING_GCC_TRUE@AM_CFLAGS = \
-@USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
-@USING_GCC_FALSE@AM_CFLAGS = \
-@USING_GCC_FALSE@@LIBGCJ_CFLAGS@
+@USING_GCC_TRUE@AM_CFLAGS = @USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
+@USING_GCC_FALSE@AM_CFLAGS = @USING_GCC_FALSE@@LIBGCJ_CFLAGS@
 
 JCFLAGS = -g
 JC1FLAGS = -g @LIBGCJ_JAVAFLAGS@
@@ -225,8 +206,7 @@ extra_headers = java/lang/Object.h java/lang/Class.h
 
 NM = nm
 
-@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = \
-@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
+@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = @NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
 
 CONVERT_DIR = gnu/gcj/convert
 
@@ -282,6 +262,8 @@ gnu/gcj/convert/UnicodeToBytes.java
 special_java_source_files = java/lang/Class.java java/lang/Object.java
 
 awt_java_source_files = \
+gnu/gcj/awt/BitMaskExtent.java \
+gnu/gcj/awt/Buffers.java \
 java/awt/AWTError.java \
 java/awt/AWTEvent.java \
 java/awt/AWTEventMulticaster.java \
@@ -291,7 +273,6 @@ java/awt/Adjustable.java \
 java/awt/BorderLayout.java \
 java/awt/CheckboxGroup.java \
 java/awt/Color.java \
-java/awt/ColorModel.java \
 java/awt/Component.java        \
 java/awt/ComponentOrientation.java \
 java/awt/Container.java        \
@@ -331,6 +312,9 @@ java/awt/TextComponent.java \
 java/awt/Toolkit.java \
 java/awt/Transparency.java \
 java/awt/Window.java \
+java/awt/color/ColorSpace.java \
+java/awt/color/ICC_ColorSpace.java \
+java/awt/color/ICC_Profile.java \
 java/awt/event/AWTEventListener.java \
 java/awt/event/ActionEvent.java        \
 java/awt/event/ActionListener.java \
@@ -378,9 +362,23 @@ java/awt/geom/PathIterator.java    \
 java/awt/geom/Point2D.java \
 java/awt/geom/Rectangle2D.java \
 java/awt/geom/RectangularShape.java \
+java/awt/image/ColorModel.java \
+java/awt/image/ComponentColorModel.java \
+java/awt/image/ComponentSampleModel.java \
+java/awt/image/DataBuffer.java \
+java/awt/image/DataBufferByte.java \
+java/awt/image/DataBufferInt.java \
+java/awt/image/DataBufferUShort.java \
+java/awt/image/DirectColorModel.java \
 java/awt/image/ImageConsumer.java \
 java/awt/image/ImageObserver.java \
 java/awt/image/ImageProducer.java \
+java/awt/image/IndexColorModel.java \
+java/awt/image/PackedColorModel.java \
+java/awt/image/Raster.java \
+java/awt/image/SampleModel.java \
+java/awt/image/SinglePixelPackedSampleModel.java \
+java/awt/image/WritableRaster.java \
 java/awt/peer/ButtonPeer.java \
 java/awt/peer/CanvasPeer.java \
 java/awt/peer/CheckboxMenuItemPeer.java        \
@@ -991,7 +989,8 @@ DIST_SUBDIRS =  @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include
 DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/$(srcdir)/$(CONVERT_DIR)/make-trie.P .deps/boehm.P \
 .deps/defineclass.P .deps/exception.P .deps/gij.P \
-.deps/gnu/gcj/RawData.P .deps/gnu/gcj/convert/BytesToUnicode.P \
+.deps/gnu/gcj/RawData.P .deps/gnu/gcj/awt/BitMaskExtent.P \
+.deps/gnu/gcj/awt/Buffers.P .deps/gnu/gcj/convert/BytesToUnicode.P \
 .deps/gnu/gcj/convert/Convert.P .deps/gnu/gcj/convert/Input_8859_1.P \
 .deps/gnu/gcj/convert/Input_EUCJIS.P \
 .deps/gnu/gcj/convert/Input_JavaSrc.P \
@@ -1050,14 +1049,13 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/awt/AWTEventMulticaster.P .deps/java/awt/AWTException.P \
 .deps/java/awt/ActiveEvent.P .deps/java/awt/Adjustable.P \
 .deps/java/awt/BorderLayout.P .deps/java/awt/CheckboxGroup.P \
-.deps/java/awt/Color.P .deps/java/awt/ColorModel.P \
-.deps/java/awt/Component.P .deps/java/awt/ComponentOrientation.P \
-.deps/java/awt/Container.P .deps/java/awt/Cursor.P \
-.deps/java/awt/Dimension.P .deps/java/awt/Event.P \
-.deps/java/awt/EventDispatchThread.P .deps/java/awt/EventQueue.P \
-.deps/java/awt/Font.P .deps/java/awt/FontMetrics.P \
-.deps/java/awt/Frame.P .deps/java/awt/Graphics.P \
-.deps/java/awt/GraphicsConfiguration.P \
+.deps/java/awt/Color.P .deps/java/awt/Component.P \
+.deps/java/awt/ComponentOrientation.P .deps/java/awt/Container.P \
+.deps/java/awt/Cursor.P .deps/java/awt/Dimension.P \
+.deps/java/awt/Event.P .deps/java/awt/EventDispatchThread.P \
+.deps/java/awt/EventQueue.P .deps/java/awt/Font.P \
+.deps/java/awt/FontMetrics.P .deps/java/awt/Frame.P \
+.deps/java/awt/Graphics.P .deps/java/awt/GraphicsConfiguration.P \
 .deps/java/awt/IllegalComponentStateException.P .deps/java/awt/Image.P \
 .deps/java/awt/Insets.P .deps/java/awt/ItemSelectable.P \
 .deps/java/awt/Label.P .deps/java/awt/LayoutManager.P \
@@ -1071,6 +1069,8 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/awt/Shape.P .deps/java/awt/TextArea.P \
 .deps/java/awt/TextComponent.P .deps/java/awt/Toolkit.P \
 .deps/java/awt/Transparency.P .deps/java/awt/Window.P \
+.deps/java/awt/color/ColorSpace.P .deps/java/awt/color/ICC_ColorSpace.P \
+.deps/java/awt/color/ICC_Profile.P \
 .deps/java/awt/event/AWTEventListener.P \
 .deps/java/awt/event/ActionEvent.P \
 .deps/java/awt/event/ActionListener.P \
@@ -1109,9 +1109,21 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/awt/geom/PathIterator.P .deps/java/awt/geom/Point2D.P \
 .deps/java/awt/geom/Rectangle2D.P \
 .deps/java/awt/geom/RectangularShape.P \
+.deps/java/awt/image/ColorModel.P \
+.deps/java/awt/image/ComponentColorModel.P \
+.deps/java/awt/image/ComponentSampleModel.P \
+.deps/java/awt/image/DataBuffer.P .deps/java/awt/image/DataBufferByte.P \
+.deps/java/awt/image/DataBufferInt.P \
+.deps/java/awt/image/DataBufferUShort.P \
+.deps/java/awt/image/DirectColorModel.P \
 .deps/java/awt/image/ImageConsumer.P \
 .deps/java/awt/image/ImageObserver.P \
-.deps/java/awt/image/ImageProducer.P .deps/java/awt/peer/ButtonPeer.P \
+.deps/java/awt/image/ImageProducer.P \
+.deps/java/awt/image/IndexColorModel.P \
+.deps/java/awt/image/PackedColorModel.P .deps/java/awt/image/Raster.P \
+.deps/java/awt/image/SampleModel.P \
+.deps/java/awt/image/SinglePixelPackedSampleModel.P \
+.deps/java/awt/image/WritableRaster.P .deps/java/awt/peer/ButtonPeer.P \
 .deps/java/awt/peer/CanvasPeer.P \
 .deps/java/awt/peer/CheckboxMenuItemPeer.P \
 .deps/java/awt/peer/CheckboxPeer.P .deps/java/awt/peer/ChoicePeer.P \
@@ -1751,7 +1763,7 @@ distdir: $(DISTFILES)
        @for file in $(DISTFILES); do \
          d=$(srcdir); \
          if test -d $$d/$$file; then \
-           cp -pr $$/$$file $(distdir)/$$file; \
+           cp -pr $$d/$$file $(distdir)/$$file; \
          else \
            test -f $(distdir)/$$file \
            || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
diff --git a/libjava/gnu/gcj/awt/BitMaskExtent.java b/libjava/gnu/gcj/awt/BitMaskExtent.java
new file mode 100644 (file)
index 0000000..2da39f8
--- /dev/null
@@ -0,0 +1,51 @@
+/* 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 gnu.gcj.awt;
+
+/** 
+ * Simple transparent utility class that can be used to perform bit
+ * mask extent calculations.
+ */
+public final class BitMaskExtent
+{
+  /** The number of the least significant bit of the bit mask extent. */
+  public byte leastSignificantBit;
+
+  /** The number of bits in the bit mask extent. */
+  public byte bitWidth;
+  
+  /**
+   * Set the bit mask. This will calculate and set the leastSignificantBit
+   * and bitWidth fields.
+   *
+   * @see #leastSignificantBit
+   * @see #bitWidth
+   */
+  public void setMask(long mask)
+  {
+    leastSignificantBit = 0;
+    bitWidth = 0;
+    if (mask == 0) return;
+    long shiftMask = mask;
+    for (; (shiftMask&1) == 0; shiftMask >>>=1) leastSignificantBit++;
+    for (; (shiftMask&1) != 0; shiftMask >>>=1) bitWidth++;
+    
+    if (shiftMask != 0)
+      throw new IllegalArgumentException("mask must be continuous");
+  }
+  
+  /** 
+   * Calculate the bit mask based on the values of the
+   * leastSignificantBit and bitWidth fields.
+   */
+  public long toMask()
+  {
+    return ((1<<bitWidth)-1) << leastSignificantBit;
+  }  
+}
diff --git a/libjava/gnu/gcj/awt/Buffers.java b/libjava/gnu/gcj/awt/Buffers.java
new file mode 100644 (file)
index 0000000..d4ad3a8
--- /dev/null
@@ -0,0 +1,168 @@
+/* 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 gnu.gcj.awt;
+
+import java.awt.image.*;
+
+/** 
+ * Utility class for creating and accessing data buffers of arbitrary
+ * data types.
+ */
+public final class Buffers
+{
+  /**
+   * Create a data buffer of a particular type.
+   *
+   * @param dataType the desired data type of the buffer.
+   * @param data an array containing data, or null
+   * @param size the size of the data buffer bank
+   */
+  public static DataBuffer createBuffer(int dataType, Object data,
+                                       int size)
+  {
+    if (data == null) return createBuffer(dataType, size, 1);
+
+    return createBufferFromData(dataType, data, size);
+  }
+
+
+  /**
+   * Create a data buffer of a particular type.
+   *
+   * @param dataType the desired data type of the buffer.
+   * @param size the size of the data buffer bank
+   */
+  public static DataBuffer createBuffer(int dataType, int size) {
+    return createBuffer(dataType, size, 1);
+  }
+
+  /**
+   * Create a data buffer of a particular type.
+   *
+   * @param dataType the desired data type of the buffer.
+   * @param size the size of the data buffer bank
+   * @param numBanks the number of banks the buffer should have
+   */
+  public static DataBuffer createBuffer(int dataType, int size, int numBanks)
+  {
+    switch (dataType)
+      {
+      case DataBuffer.TYPE_BYTE:
+       return new DataBufferByte(size, numBanks);
+      case DataBuffer.TYPE_USHORT:
+       return new DataBufferUShort(size, numBanks);
+      case DataBuffer.TYPE_INT:
+       return new DataBufferInt(size, numBanks);
+      default:
+       throw new UnsupportedOperationException();
+      }
+  }
+  
+  /**
+   * Create a data buffer of a particular type.
+   *
+   * @param dataType the desired data type of the buffer
+   * @param data an array containing the data
+   * @param size the size of the data buffer bank
+   */
+  public static DataBuffer createBufferFromData(int dataType, Object data,
+                                               int size)
+  {
+    switch (dataType)
+      {
+      case DataBuffer.TYPE_BYTE:
+       return new DataBufferByte((byte[]) data, size);
+      case DataBuffer.TYPE_USHORT:
+       return new DataBufferUShort((short[]) data, size);
+      case DataBuffer.TYPE_INT:
+       return new DataBufferInt((int[]) data, size);
+      default:
+       throw new UnsupportedOperationException();
+      }
+  }
+
+  /** 
+   * Return the data array of a data buffer, regardless of the data
+   * type.
+   *
+   * @return an array of primitive values. The actual array type
+   * depends on the data type of the buffer.
+   */
+  public static Object getData(DataBuffer buffer)
+  {
+    if (buffer instanceof DataBufferByte)
+      return ((DataBufferByte) buffer).getData();
+    if (buffer instanceof DataBufferUShort)
+      return ((DataBufferUShort) buffer).getData();
+    if (buffer instanceof DataBufferInt)
+      return ((DataBufferInt) buffer).getData();
+    throw new ClassCastException("Unknown data buffer type");
+  }
+
+    
+  /**
+   * Copy data from array contained in data buffer, much like
+   * System.arraycopy. Create a suitable destination array if the
+   * given destination array is null.
+   */
+  public static Object getData(DataBuffer src, int srcOffset,
+                              Object dest,  int destOffset,
+                              int length)
+  {
+    Object from;
+    if (src instanceof DataBufferByte)
+      {
+       from = ((DataBufferByte) src).getData();
+       if (dest == null) dest = new byte[length+destOffset];
+      }
+    else if (src instanceof DataBufferUShort)
+      {
+       from = ((DataBufferUShort) src).getData();
+       if (dest == null) dest = new short[length+destOffset];
+      }
+    else if (src instanceof DataBufferInt)
+      {
+       from = ((DataBufferInt) src).getData();
+       if (dest == null) dest = new int[length+destOffset];
+      }
+    else
+      {
+       throw new ClassCastException("Unknown data buffer type");
+      }
+    
+    System.arraycopy(from, srcOffset, dest, destOffset, length);
+    return dest;
+  }
+  
+  /**
+   * @param bits the width of a data element measured in bits
+   *
+   * @return the smallest data type that can store data elements of
+   * the given number of bits, without any truncation.
+   */
+  public static int smallestAppropriateTransferType(int bits)
+  {
+    if (bits <= 8)
+      {
+       return DataBuffer.TYPE_BYTE;
+      }
+    else if (bits <= 16)
+      {
+       return DataBuffer.TYPE_USHORT;
+      } 
+    else if (bits <= 32)
+      {
+       return DataBuffer.TYPE_INT;
+      }
+    else
+      {
+       return DataBuffer.TYPE_UNDEFINED;
+      }
+  }
+}
diff --git a/libjava/java/awt/ColorModel.java b/libjava/java/awt/ColorModel.java
deleted file mode 100644 (file)
index 0e58df1..0000000
+++ /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 (file)
index 0000000..e6e1251
--- /dev/null
@@ -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 (file)
index 0000000..90ff88c
--- /dev/null
@@ -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 (file)
index 0000000..475aa55
--- /dev/null
@@ -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 (file)
index 0000000..ceee278
--- /dev/null
@@ -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 (file)
index 0000000..deb40ff
--- /dev/null
@@ -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 (file)
index 0000000..f825d48
--- /dev/null
@@ -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 (file)
index 0000000..b40dac1
--- /dev/null
@@ -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 (file)
index 0000000..67b4f5f
--- /dev/null
@@ -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 (file)
index 0000000..560fb9c
--- /dev/null
@@ -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 (file)
index 0000000..7963c38
--- /dev/null
@@ -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 (file)
index 0000000..8e092d1
--- /dev/null
@@ -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();
+  }
+}
index 37214d7b7693cd1b1e4abe5cbfe3e77f63d25659..26519cbe467bee9d13fa0d14301c80655ea6112f 100644 (file)
@@ -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 (file)
index 0000000..e35fcd6
--- /dev/null
@@ -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 (file)
index 0000000..a72ae2d
--- /dev/null
@@ -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 (file)
index 0000000..46786d9
--- /dev/null
@@ -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 (file)
index 0000000..3368c83
--- /dev/null
@@ -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 (file)
index 0000000..3baea04
--- /dev/null
@@ -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 (file)
index 0000000..6667256
--- /dev/null
@@ -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);
+  }
+}