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