diff options
author | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-07-23 21:28:32 +0000 |
---|---|---|
committer | Andrew John Hughes <gnu_andrew@member.fsf.org> | 2006-07-23 21:28:32 +0000 |
commit | ef8f9342adc610b1e8fcfb71c5b2400d29f1c8fa (patch) | |
tree | a60d6813f0454b3b28c337e922492b4eec466fb9 | |
parent | ee82dd6eae151a860dff851492809c46b3818796 (diff) | |
download | classpath-ef8f9342adc610b1e8fcfb71c5b2400d29f1c8fa.tar.gz |
2006-07-23 Andrew John Hughes <gnu_andrew@member.fsf.org>
* Merge of HEAD to generics-branch for
2006-07-16 to 2006-07-23.
117 files changed, 7526 insertions, 1551 deletions
@@ -1,3 +1,94 @@ +2006-07-23 Mark Wielaard <mark@klomp.org> + + * configure.ac: Check for moc and moc-qt4. + +2006-07-23 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/Kernel.java: API doc updates. + +2006-07-22 Andreas Tobler <a.tobler@schweiz.ch> + + * gnu/java/awt/peer/gtk/CairoSurface.java: Optimize pixel swap code a + bit more. + +2006-07-22 Mark Wielaard <mark@klomp.org> + + * java/lang/Iterable.java: Import all of java.util. + * lib/mkcollections.pl.in (javautilclasses): Add Iterable. + * lib/Makefile.am: Only search for .java files in COLLECTIONS_PREFIX. + +2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * doc/vmintegration.texinfo: + Document getType(String). + * gnu/java/lang/management/MemoryPoolMXBeanImpl.java, + * java/lang/management/MemoryPoolMXBean.java: + (getType()): Implemented. + * vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java + (getType(String)): Implemented. + +2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * doc/vmintegration.texinfo: + Move end of itemization block. + +2006-07-22 Robert Schuster <robertschuster@fsfe.org> + + * javax/swing/plaf/metal/MetalLookAndFeel.java: + (initComponentDefaults): Added new properties, added comments. + +2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * doc/vmintegration.texinfo: + Mention callback methods. + * gnu/java/lang/management/MemoryMXBeanImpl.java: + (fireNotification(String,String,long,long,long,long,long)): + Made package-private. + (fireThresholdExceededNotification(String,long,long,long, + long,long)): Likewise. + (fireCollectionThresholdExceededNotification(String,long, + long,long,long,long)): Likewise. + * java/lang/management/MemoryMXBean.java: + Document notifications. + +2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * gnu/java/lang/management/MemoryMXBeanImpl.java: + (fireNotification(String,String,long,long,long,long,long)): + Implemented. + (fireThresholdExceededNotification(String,long,long,long, + long,long)): Likewise. + (fireCollectionThresholdExceededNotification(String,long, + long,long,long,long)): Likewise. + * java/lang/management/MemoryNotificationInfo.java: + Use composite type from MemoryMXBeanImpl. + * javax/management/openmbean/CompositeData.java: + Correct documentation. + * javax/management/openmbean/CompositeDataSupport.java, + * javax/management/openmbean/InvalidKeyException.java: + New files. + +2006-07-22 Raif S. Naffah <raif@swiftdsl.com.au> + + * gnu/java/security/util/IntegerUtil.java: New file. + +2006-07-22 Raif S. Naffah <raif@swiftdsl.com.au> + + PR Classpath/28100 + * gnu/javax/crypto/cipher/TripleDES.java: Updated documentation. + (KEY_SIZE): Likewise. + (adjustParity(int,byte[],int): New method. + (adjustParity(byte[],int): Call above method with 3 as 1st argument. + (isParityAdjusted(int,byte[],int)): New method. + (isParityAdjusted): Call above method with 3 as 1st argument. + (keySizes): Add 8 and 16 as other valid key sizes. + (makeKey): Amended to cater for 1, 2 and 3 independent DES keys. + +2006-07-22 Andreas Tobler <a.tobler@schweiz.ch> + + * gnu/java/awt/peer/gtk/CairoSurface.java (CairoSurface): Rearrange + code for the pixel swap routine to be more efficient. + 2006-07-21 Carsten Neumann <cn-develop@gmx.net> * java/util/CopyOnWriteArrayList.java (indexOf(E, int)): New method. @@ -5,6 +96,479 @@ (add(E)): Increase the size of newData array by one. (add(int, E)): Likewise. +2006-07-20 Lillian Angel <langel@redhat.com> + + * gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java: + Removed unused fields. + (GtkMouseDragGestureRecognizer): Removed initializations. + +2006-07-20 Lillian Angel <langel@redhat.com> + + * gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java + (GtkMouseDragGestureRecognizer): New constructor. + (GtkMouseDragGestureRecognizer): New constructor. + (GtkMouseDragGestureRecognizer): New constructor. + (mouseClicked): Removed FIXME. + (mousePressed): Implemented. + (mouseReleased): Implemented. + (mouseEntered): Implemented. + (mouseDragged): Implemented to check mouse point and trigger origin. + (mouseMoved): Removed FIXME. + (getDropActionFromEvent): New helper function used to convert mouse event + modifiers to a drop action. + * java/awt/dnd/DragSource.java + (getDragThreshold): Changed to return some arbitrary value for testing + purposes. + +2006-07-20 Roman Kennke <kennke@aicas.com> + + * java/awt/LightweightDispatcher.java + (findTarget): Also consider components that have their eventMask + set, for compatibility with stonage AWT. Optimized check + for MouseListener. + (handleMouseEvent): Likewise. + +2006-07-20 Roman Kennke <kennke@aicas.com> + + * javax/swing/JTable.java + (tableChanged): Split out handling of the event into multiple + subroutines. + (handleCompleteChange): New method. Clear the selection and + check the lead/anchor indices. + (handleInsert): New method. Check the lead/anchor indices. + Optimized repainting. + (handleDelete): New method. Check the lead/anchor indices. + Optimized repainting. + (handleUpdate): New method. Optimized repainting. + (checkSelection): New helper method. + (setSelectionModel): Update lead/anchor indices. + +2006-07-20 Lillian Angel <langel@redhat.com> + + PR 28440 + * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java + (dispose): Reset all fields. + +2006-07-20 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/x/XToolkit.java + (createImage(InputStream)): Only copy image to Pixmap if + it's actually opaque. Transparent images are left as + BufferedImage and composited later onto the screen. + * gnu/java/awt/peer/x/XGraphics.java + (XGraphics): Fetch some parameters for image rendering. + (drawImage): Added special handling of transparent images. + (getRGB): New helper method. + (setRGB): New helper method. + +2006-07-20 Roman Kennke <kennke@aicas.com> + + * gnu/javax/imageio/IIOInputStream.java: New class. Wraps + ImageInputStreams as normal InputStreams. + * gnu/javax/imageio/gif/GIFStream.java: + Moved to gnu/javax/imageio/IIOInputStream.java. + * gnu/javax/imageio/gif/GIFImageReader.java + (readImage): Use IIOInputStream. + * gnu/javax/imageio/gif/GIFImageReaderSpi.java + (canDecodeInput): Use IIOInputStream. + * gnu/javax/imageio/png/PNGException.java: Make subclass + of IOException. + * gnu/javax/imageio/png/PNGImageReader.java: New class. + Implements the ImageIO ImageReader for PNG. + * gnu/javax/imageio/png/PNGImageReaderSpi.java: New class. + Implements the ImageIO ImageReaderSpi for PNG. + * javax/imageio/spi/IIORegistry.java: + (IIORegistry): Add PNGImageReaderSpi. + +2006-07-20 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/ComponentSampleModel.java + (getPixel): Added argument check, + (getSample): Modified exception message. + +2006-07-20 David Gilbert <david.gilbert@object-refinery.com> + + PR Classpath/28422 + * java/awt/image/ConvolveOp.java + (filter(Raster, WritableRaster)): Reimplemented, + (fillEdge): New private method. + +2006-07-19 Keith Seitz <keiths@redhat.com> + + * include/jvmti.h (JVMTI_VERSION_1_0): Define. + (JVMTI_VERSION): Define. + +2006-07-19 Roman Kennke <kennke@aicas.com> + + * resource/gnu/regexp/MessagesBundle.properties, + * resource/gnu/regexp/MessagesBundle_fr.properties, + * resource/gnu/regexp/MessagesBundle_it.properties: + Moved to resource/gnu/java/util/regex. + * resource/gnu/java/util/regex/MessagesBundle.properties, + * resource/gnu/java/util/regex/MessagesBundle_fr.properties, + * resource/gnu/java/util/regex/MessagesBundle_it.properties: + New files. + * gnu/java/util/regex/RE.java + Use new resource bundle location. + +2006-07-19 Roman Kennke <kennke@aicas.com> + + * javax/swing/JComponent.java + (paintChildren): Refactored. The paintChildrenOptimized method + has been moved back in here. Added locking of the tree and + only check for completely obscured child components + when not optimized drawing enabled. Use Graphics.create() to + protect from irreversible changes. + (isCompletelyObscured): New helper method. + (paintComponent): Also use Graphics.create() for Graphics2D, + to protect from irreverible changes. + (clipAndTranslateGraphics): Refactored to use more efficient + iterative (vs recursive) approach. + * javax/swing/RepaintManager.java + (getOffscreenBuffer): Create image from root component. + +2006-07-19 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/x/XGraphics.java + (translate): Don't set the clip on the X server. + (clipRect): Use setXClip() to set the clip on the X server. + (hitClip): More efficient and correct implementation. + (setClip): Use setXClip() to set the clip on the X server. + (setClip(Shape)): Use setXClip() to set the clip on the X server. + (copyArea): Translate and clip the source rectangle correctly. + (dispose): Only flush when object is not yet disposed. + (clone): Use setXClip() to set the clip on the X server. + +2006-07-19 Sven de Marothy <sven@physto.se> + + * gnu/javax/imageio/png/PNGChunk.java, + * gnu/javax/imageio/png/PNGData.java, + * gnu/javax/imageio/png/PNGDecoder.java, + * gnu/javax/imageio/png/PNGEncoder.java, + * gnu/javax/imageio/png/PNGException.java, + * gnu/javax/imageio/png/PNGFile.java, + * gnu/javax/imageio/png/PNGFilter.java, + * gnu/javax/imageio/png/PNGGamma.java, + * gnu/javax/imageio/png/PNGHeader.java, + * gnu/javax/imageio/png/PNGICCProfile.java, + * gnu/javax/imageio/png/PNGPalette.java, + * gnu/javax/imageio/png/PNGPhys.java, + * gnu/javax/imageio/png/PNGTime.java: + New files. + +2006-07-19 Sven de Marothy <sven@physto.se> + + * java/net/Inet6Address.java: + (getScopedId, getScopedInterface): New methods. + +2006-07-19 Lillian Angel <langel@redhat.com> + + * examples/gnu/classpath/examples/awt/Demo.java + (DragDropWindow): Fixed typo in Label text. + * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java + (GtkDragSourceContextPeer): Removed unneeded initialization for field. + (startDrag): Initialized context field. + (transferablesFlavorsChanged): Removed FIXME. Nothing is done in this + function. + (dragEnter): New function. + (dragExit): Likewise. + (dragDropEnd): Likewise. + (dragMouseMoved): Likewise. + (dragOver): Likewise. + (dragActionChanged): Likewise. + +2006-07-19 Raif S. Naffah <raif@swiftdsl.com.au> + + PR Classpath/26302 + * resource/java/security/classpath.security: Updated copyright year. + (auth.login.defaultCallbackHandler): New property; set to our default + callback handler. This is needed by the LoginContext when no callback + handler was specified. + * javax/security/auth/login/LoginContext.java: Updated copyright year. + (LoginContext(4)): Assign passed parameters to local fields before invoking + lookup method. + +2006-07-19 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/x/XGraphics.java + (drawImage(Image,int,int,int,int,int,int,int,int,ImageObserver)): + Fixed ordering of parameters. + +2006-07-18 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * gnu/java/lang/management/MemoryMXBeanImpl.java: + (MemoryMXBeanImpl()): Implemented. + (ListenerData): New private class. + (addNotificationListener(NotificationListener, + NotificationFilter, Object)): Implemented. + (getNotificationInfo()): Likewise. + (removeNotificationListener(NotificationListener)): + Likewise. + (removeNotificationListener(NotificationListener, + NotificationFilter, Object)): Likewise. + +2006-07-18 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/x/XFontPeer.java + (encodeFont): Be more flexible with font sizes. + (validSize): New helper method. + * gnu/java/awt/peer/x/XGraphics.java + (drawImage(Image,int,int,int,int,int,int,int,int,ImageObserver)): + Implemented. + (drawImage(Image,int,int,int,int,int,int,int,int,Color,ImageObserver)): + Implemented. + * gnu/java/awt/peer/x/XImage.java + (properties): New field. + (getProperty): Implemented. + * resource/gnu/java/awt/peer/x/fonts.properties: + Added copyright header. Fixed font size field. + +2006-07-18 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/BandedSampleModel.java + (createDataBuffer): New method override, + * java/awt/image/ByteLookupTable.java + (ByteLookupTable(int, byte[][])): Create new array to hold references, + (ByteLookuptable(int, byte[])): Check for null array, + * java/awt/image/ComponentSampleModel.java + (createDataBuffer): Removed unnecessary braces, + (getSample): Check (x, y) is within bounds, + * java/awt/image/ShortLookupTable.java + (ShortLookupTable(int, short[][])): Create new array to hold references, + (ShortLookupTable(int, short[])): Check for null array, + (getTable): Added API docs, + (lookupPixel): Source reformatting. + +2006-07-18 Tania Bento <tbento@redhat.com> + + * java/awt/GridLayout.java + (setHgap): Illegal Argument Exception should not be thrown if + hgap < 0. + (setVgap): Illegal Argument Exception should not be thrown if + vgap < 0. + (toString): Opening square braket ([) should appear before hgap + value, not the name of the class. + +2006-07-18 Roman Kennke <kennke@aicas.com> + + * lib/copy-vmresources.sh.in: Reverted. + * gnu/java/awt/peer/x/fonts.properties: Moved to resource/ + * resource/gnu/java/awt/peer/x/fonts.properties: New file. + +2006-07-18 Roman Kennke <kennke@aicas.com> + + * lib/copy-vmresources.sh.in: Include properties from X peers. + +2006-07-18 Raif S. Naffah <raif@swiftdsl.com.au> + + PR Classpath/27205 + * tools/gnu/classpath/tools/jarsigner/SFHelper.java (writeDSA): Check + certificate validity. + (getIssuerName): New method. + (getSubjectName): Likewise. + (getNotAfterDate): Likewise. + (getNotBeforeDate): Likewise. + * resource/gnu/classpath/tools/jarsigner/messages.properties: Added + messages for newly added messages in SFHelper. + +2006-07-18 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/x/XDialogPeer.java: New class. + * gnu/java/awt/peer/x/XEventPump.java + (handleEvent): Cast to XWindowPeer rather than XFramePeer. + * gnu/java/awt/peer/x/XFramePeer.java + Made a subclass of XWindowPeer, rather than SwingFramePeer. + * gnu/java/awt/peer/x/XGraphics.java + Made subclass of Graphics rather than Graphics2D. Removed + all Graphics2D specific method stubs. + (setColor): Map colors using the X color map that is + stored in XToolkit. + * gnu/java/awt/peer/x/XToolkit.java + (colorMap): New field. + (getLocalGraphicsEnvironment): Return new XGraphicsEnvironment + instance. + (createDialog): Implemented. + (createImage(ImageProducer)): Implemented. + (createImage(InputStream)): Use createImage(ImageProducer) + to convert the BufferedImage to an XImage. + * gnu/java/awt/peer/x/XWindowPeer.java + (XWindowPeer): Removed debug output. + +2006-07-18 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/BufferedImageOp.java: API docs added, + * java/awt/image/RasterOp.java: Likewise. + +2006-07-18 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/Graphics2D.java: API docs updated. + +2006-07-18 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/WritableRaster.java: Added API docs and reformatted + source code. + +2006-07-18 Sven de Marothy <sven@physto.se> + + * java/net/Inet6Address.java: + Add 1.5 serialized fields. + (getByAddress): New methods. + (readObject, writeObject): New methods. + (equals): Reimplement. + +2006-07-18 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/Raster.java: Added API docs and reformatted source + code. + +2006-07-18 Andreas Tobler <a.tobler@schweiz.ch> + + * gnu/java/awt/peer/gtk/BufferedImageGraphics.java: Remove unneeded + imports. + * gnu/java/awt/peer/gtk/CairoSurface.java: Likewise. + * gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java: Likewise. + * gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java: Likewise. + * gnu/java/awt/peer/gtk/GdkFontPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GdkPixbufDecoder.java: Likewise. + * gnu/java/awt/peer/gtk/GtkButtonPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkClipboardNotifier.java: Likewise. + * gnu/java/awt/peer/gtk/GtkComponentPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkContainerPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkDialogPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkFramePeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkImage.java: Likewise. + * gnu/java/awt/peer/gtk/GtkImageConsumer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkMenuBarPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkMenuItemPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkPanelPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkScrollbarPeer.java: Likewise. + * gnu/java/awt/peer/gtk/GtkWindowPeer.java: Likewise. + * gnu/java/awt/peer/gtk/VolatileImageGraphics.java: Likewise. + +2006-07-17 Andreas Tobler <a.tobler@schweiz.ch> + + * javax/swing/text/html/HTMLEditorKit.java: Rearrange import statements + to make it compile again under jikes. Note added. + +2006-07-17 Lillian Angel <langel@redhat.com> + + * examples/gnu/classpath/examples/awt/Demo.java + (Demo): Added new window for DnD demo. + (DragDropWindow): New class. + * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java: + Added new fields and declarations for native functions. + (GtkDragSourceContextPeer): Implemented. + (getComponentPeer): New function. + (startDrag): Partially implemented. + (getCursor): Implemented. + (setCursor): Implemented. + * include/GtkDragSourceContextPeer.h: New file. + * include/Makefile.am: Added new header file. + * java/awt/Component.java + (addNotify): Added call to the dropTarget's addNotify. + * java/awt/dnd/DragSource.java + (startDrag): Fixed code to use shared instances of peer and + context. + (getDragThreshold): Added stub. + * java/awt/dnd/DropTarget.java + (DropTarget): Implemented fully. + (addNotify): Added code to get the peer of the parent that is + not lightweight. + * java/awt/dnd/DropTargetDragEvent.java + (getTransferable): Added stub. + * native/jni/gtk-peer/GtkDragSourceContextPeer.c: New file. + * native/jni/gtk-peer/Makefile.am: Added new c file. + * gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java: + Changed to extend GtkGenericPeer. + (GtkDropTargetContextPeer): New constructor. + * gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java: + Changed to extend GtkGenericPeer. + (GtkDropTargetContextPeer): New constructor. + +2006-07-17 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/SinglePixelPackedSampleModel.java + (createSubsetSampleModel): Added argument check and API docs. + +2006-07-17 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/x/XGraphics.java + (copyArea): Implemented. + +2006-07-17 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/SinglePixelPackedSampleModel.java + (getSampleSize): Return copy of array, + (getOffset): Added API docs, + (getScanlineStride): Likewise, + (hashCode): Implemented. + +2006-07-17 David Gilbert <david.gilbert@object-refinery.com> + + * java/awt/image/MultiPixelPackedSampleModel.java + (getOffset): Updated API docs and source reformatting, + (getBitOffset): Source reformatting only, + (getDataElements): Likewise, + (getPixel): Likewise, + (getPixels): Removed method override, + (setDataElements): Reimplemented. + +2006-07-17 Gary Benson <gbenson@redhat.com> + + * resource/META-INF/services/.cvsignore: New file. + * lib/.cvsignore: Updated. + +2006-07-17 Roman Kennke <kennke@aicas.com> + + * javax/swing/plaf/basic/BasicButtonListener.java + (propertyChange): Only do the text layout caching as long + as the noGraphics2D property isn't set. + * javax/swing/plaf/basic/BasicMenuItemUI.java + (PropertyChangeHandler.propertyChange): Only do the text layout + caching as long as the noGraphics2D property isn't set. + +2006-07-17 Roman Kennke <kennke@aicas.com> + + * gnu/java/awt/peer/x/XGraphicsEnvironment.java + (XGraphicsEnvironment): Make constructor public so that it + can be called via Class.forName().newInstance(). + * gnu/java/awt/peer/x/XImage.java + (XImage): Fetch GraphicsEnvironment via + GraphicsEnvironment.getLocalGraphicsEnvironment() rather + than the XToolkit method, to avoid double instantiation + of the XGraphicsEnvironment. + * gnu/java/awt/peer/x/XToolkit.java + (env): Removed field. + (getLocalGraphicsEnvironment): Removed impl. This method + should not be called since we set the graphicsenv property + in the constructor. + +2006-07-16 Andrew John Hughes <gnu_andrew@member.fsf.org> + + * java/util/UUID.java: + (compareTo(Object)): Call compareTo(UUID). + (compareTo(UUID)): Implemented. + +2006-07-16 Tom Tromey <tromey@redhat.com> + + * java/lang/StrictMath.java (cbrt): Added '@since'. + +2006-07-16 Carsten Neumann <cn-develop@gmx.net> + + * java/lang/StrictMath.java (cbrt): New method. + (getLowDWord): New helper method. + (getHighDWord): Likewise. + (buildDouble): Likewise. + (CBRT_B1): New field. + (CBRT_B2): Likewise. + (CBRT_C): Likewise. + (CBRT_D): Likewise. + (CBRT_E): Likewise. + (CBRT_F): Likewise. + (CBRT_G): Likewise. + 2006-07-16 Andrew John Hughes <gnu_andrew@member.fsf.org> * javax/management/MBeanInfo.java: diff --git a/configure.ac b/configure.ac index f5a9a1c03..3261a1765 100644 --- a/configure.ac +++ b/configure.ac @@ -490,6 +490,7 @@ if test "x${COMPILE_JNI}" = xyes; then QT_CFLAGS="$QT_CFLAGS -I$EXTRA_QT_INCLUDE_DIR", AC_MSG_WARN([QWidget not found]))) AC_CHECK_PROG(MOC, [moc], [moc]) + AC_CHECK_PROG(MOC, [moc-qt4], [moc-qt4]) fi if test "x$HAVE_QT4" = "xno"; then AC_MSG_NOTICE([Looking for QT_CFLAGS and QT_LIBS without pkg-config]) diff --git a/doc/vmintegration.texinfo b/doc/vmintegration.texinfo index bd7464e49..e7f85d088 100644 --- a/doc/vmintegration.texinfo +++ b/doc/vmintegration.texinfo @@ -1551,6 +1551,9 @@ of names of memory managers which manage the specified pool. @item @code{(getPeakUsage(String))} -- Returns a @code{java.lang.management.MemoryUsage} object for the peak usage level of the specified pool. +@item @code{(getType(String))} -- Returns a string containing +either @code{"HEAP"} or @code{"NON_HEAP"} which indicates the type of +memory used by the specified pool. @item @code{(getUsage(String))} -- Returns a @code{java.lang.management.MemoryUsage} object for the current usage level of the specified pool. @@ -1649,6 +1652,26 @@ the group. @item @code{java.lang.ThreadGroup.removeThread(Thread)} Call this method from @code{Thread} when a @code{Thread} is stopped or destroyed. + +@item @code{gnu.java.lang.management.MemoryMXBeanImpl.fireThresholdExceededNotification(String, long, long, long, long)} +If the monitoring of memory usage thresholds is supported, this method +should be called when the normal usage of a memory pool crosses the +threshold, in order to emit a notification. Another notification +should not be emitted until there is an intermittent period where the +usage is again below the threshold. The parameters are the memory +pool name, the usage levels (init, used, committed and max) and the +number of times the threshold has been crossed. + +@item @code{gnu.java.lang.management.MemoryMXBeanImpl.fireCollectionThresholdExceededNotification(String, long, long, long, long)} +If the monitoring of memory usage thresholds is supported, this method +should be called when the usage of a memory pool after a garbage +collection cycle crosses the threshold, in order to emit a +notification. Another notification should not be emitted until there +is an intermittent period where the usage is again below the +threshold. The parameters are the memory pool name, the usage levels +(init, used, committed and max) and the number of times the threshold +has been crossed. + @end itemize @node VM Hooks, JNI Implementation, Classpath Hooks, Top diff --git a/examples/gnu/classpath/examples/awt/Demo.java b/examples/gnu/classpath/examples/awt/Demo.java index 5e668dde6..bd5e755cb 100644 --- a/examples/gnu/classpath/examples/awt/Demo.java +++ b/examples/gnu/classpath/examples/awt/Demo.java @@ -20,11 +20,70 @@ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA package gnu.classpath.examples.awt; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Canvas; +import java.awt.Checkbox; +import java.awt.CheckboxGroup; +import java.awt.CheckboxMenuItem; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.DisplayMode; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Label; import java.awt.List; -import java.awt.event.*; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.MenuShortcut; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.TextField; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceContext; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.dnd.InvalidDnDOperationException; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.net.URL; -import java.util.*; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; class Demo { @@ -156,6 +215,7 @@ class Demo addSubWindow ("Animation", new AnimationWindow ()); addSubWindow ("Resolution", new ResolutionWindow ()); addSubWindow ("Fullscreen", new FullscreenWindow ()); + addSubWindow ("Drag n' Drop", new DragDropWindow ()); Panel sp = new Panel(); PrettyPanel p = new PrettyPanel(); @@ -799,6 +859,141 @@ class Demo } } + static class DragDropWindow + extends SubFrame + implements ActionListener, DropTargetListener + { + DragLabel source = new DragLabel("Drag and drop me to the following Button", + Label.CENTER); + + Button target = new Button(); + + public void init() + { + source.setForeground(Color.red); + add(source, BorderLayout.NORTH); + + target.addActionListener(this); + add(target, BorderLayout.SOUTH); + + new DropTarget(target, DnDConstants.ACTION_COPY_OR_MOVE, this); + + setSize(205, 100); + + pack(); + } + + public void actionPerformed(ActionEvent e) + { + Button b = (Button) e.getSource(); + b.setLabel(""); + } + + public void dragEnter(DropTargetDragEvent e) + { + } + + public void dragExit(DropTargetEvent e) + { + } + + public void dragOver(DropTargetDragEvent e) + { + } + + public void drop(DropTargetDropEvent e) + { + try + { + Transferable t = e.getTransferable(); + + if (e.isDataFlavorSupported(DataFlavor.stringFlavor)) + { + e.acceptDrop(e.getDropAction()); + + String s; + s = (String) t.getTransferData(DataFlavor.stringFlavor); + + target.setLabel(s); + + e.dropComplete(true); + } + else + e.rejectDrop(); + } + catch (java.io.IOException e2) + { + } + catch (UnsupportedFlavorException e2) + { + } + } + + public void dropActionChanged(DropTargetDragEvent e) + { + } + + class DragLabel + extends Label + implements DragGestureListener, DragSourceListener + { + private DragSource ds = DragSource.getDefaultDragSource(); + + public DragLabel(String s, int alignment) + { + super(s, alignment); + int action = DnDConstants.ACTION_COPY_OR_MOVE; + ds.createDefaultDragGestureRecognizer(this, action, this); + } + + public void dragGestureRecognized(DragGestureEvent e) + { + try + { + Transferable t = new StringSelection(getText()); + e.startDrag(DragSource.DefaultCopyNoDrop, t, this); + } + catch (InvalidDnDOperationException e2) + { + System.out.println(e2); + } + } + + public void dragDropEnd(DragSourceDropEvent e) + { + if (e.getDropSuccess() == false) + return; + + int action = e.getDropAction(); + if ((action & DnDConstants.ACTION_MOVE) != 0) + setText(""); + } + + public void dragEnter(DragSourceDragEvent e) + { + DragSourceContext ctx = e.getDragSourceContext(); + + int action = e.getDropAction(); + if ((action & DnDConstants.ACTION_COPY) != 0) + ctx.setCursor(DragSource.DefaultCopyDrop); + else + ctx.setCursor(DragSource.DefaultCopyNoDrop); + } + + public void dragExit(DragSourceEvent e) + { + } + + public void dragOver(DragSourceDragEvent e) + { + } + + public void dropActionChanged(DragSourceDragEvent e) + { + } + } + } + static class FullscreenWindow extends SubFrame { GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); diff --git a/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java b/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java index 889f258fb..990c2140d 100644 --- a/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java +++ b/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java @@ -39,7 +39,8 @@ exception statement from your version. */ package gnu.java.awt.dnd; import java.awt.Component; -import java.awt.dnd.DragGestureEvent; +import java.awt.Point; +import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.MouseDragGestureRecognizer; @@ -48,63 +49,116 @@ import java.awt.event.MouseEvent; public class GtkMouseDragGestureRecognizer extends MouseDragGestureRecognizer { + + public GtkMouseDragGestureRecognizer (DragSource ds) + { + this(ds, null, 0, null); + } + + public GtkMouseDragGestureRecognizer (DragSource ds, Component c) + { + this (ds, c, 0, null); + } - DragSource ds; - Component c; - int actions; - DragGestureListener dgl; - - GtkMouseDragGestureRecognizer() + public GtkMouseDragGestureRecognizer (DragSource ds, Component c, int act) { - super(null); + this(ds, c, act, null); } public GtkMouseDragGestureRecognizer (DragSource ds, Component c, int act, DragGestureListener dgl) { - super (ds, c, act, dgl); + super(ds, c, act, dgl); registerListeners(); - - this.ds = ds; - this.c = c; - this.actions = act; - this.dgl = dgl; } public void mouseClicked (MouseEvent e) { - // FIXME: Not Implemented + // Nothing to do here. } public void mousePressed (MouseEvent e) { - // FIXME: Not Implemented + events.clear(); + if (getDropActionFromEvent(e) != DnDConstants.ACTION_NONE) + appendEvent(e); } public void mouseReleased (MouseEvent e) { - // FIXME: Not Implemented + events.clear(); } public void mouseEntered (MouseEvent e) { - // FIXME: Not Implemented + events.clear(); } - public void mouseExited (MouseEvent e) + public void mouseExited(MouseEvent e) { - // FIXME: Not Implemented + if (!events.isEmpty()) + if (getDropActionFromEvent(e) == DnDConstants.ACTION_NONE) + events.clear(); } public void mouseDragged(MouseEvent e) { - dgl.dragGestureRecognized(new DragGestureEvent(this, actions, e.getPoint(), - events)); + if (!events.isEmpty()) + { + int act = getDropActionFromEvent(e); + + if (act == DnDConstants.ACTION_NONE) + return; + + Point origin = ((MouseEvent) events.get(0)).getPoint(); + Point current = e.getPoint(); + int dx = Math.abs(origin.x - current.x); + int dy = Math.abs(origin.y - current.y); + int threshold = DragSource.getDragThreshold(); + + if (dx > threshold || dy > threshold) + fireDragGestureRecognized(act, origin); + else + appendEvent(e); + } } - + public void mouseMoved (MouseEvent e) { - // FIXME: Not Implemented + // Nothing to do here. + } + + private int getDropActionFromEvent(MouseEvent e) + { + int modEx = e.getModifiersEx(); + int buttons = modEx & (MouseEvent.BUTTON1_DOWN_MASK + | MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK); + if (!(buttons == MouseEvent.BUTTON1_DOWN_MASK || + buttons == MouseEvent.BUTTON2_DOWN_MASK)) + return DnDConstants.ACTION_NONE; + + // Convert modifier to a drop action + int sourceActions = getSourceActions(); + int mod = modEx + & (MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK); + switch (mod) + { + case MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK: + return DnDConstants.ACTION_LINK & sourceActions; + case MouseEvent.CTRL_DOWN_MASK: + return DnDConstants.ACTION_COPY & sourceActions; + case MouseEvent.SHIFT_DOWN_MASK: + return DnDConstants.ACTION_MOVE & sourceActions; + default: + if ((sourceActions & DnDConstants.ACTION_MOVE) != 0) + return DnDConstants.ACTION_MOVE & sourceActions; + else if ((sourceActions & DnDConstants.ACTION_COPY) != 0) + return DnDConstants.ACTION_COPY & sourceActions; + else if ((sourceActions & DnDConstants.ACTION_LINK) != 0) + return DnDConstants.ACTION_LINK & sourceActions; + } + + return DnDConstants.ACTION_NONE & sourceActions; } } diff --git a/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java b/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java index 873027290..4f9229822 100644 --- a/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java +++ b/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java @@ -38,44 +38,137 @@ exception statement from your version. */ package gnu.java.awt.dnd.peer.gtk; +import gnu.java.awt.peer.gtk.GtkGenericPeer; + +import java.awt.Component; import java.awt.Cursor; import java.awt.Image; import java.awt.Point; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragSourceContext; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; import java.awt.dnd.InvalidDnDOperationException; import java.awt.dnd.peer.DragSourceContextPeer; +import java.awt.peer.ComponentPeer; +import java.awt.peer.LightweightPeer; public class GtkDragSourceContextPeer + extends GtkGenericPeer implements DragSourceContextPeer { - - private DragGestureEvent dge; + private ComponentPeer peer; + private Cursor cursor; + private DragSourceContext context; + + native void nativeStartDrag(Image i, int x, int y, int action, String target); + native void connectSignals(ComponentPeer comp); + native void create(ComponentPeer comp); + native void nativeSetCursor(int cursor); public GtkDragSourceContextPeer(DragGestureEvent e) { - dge = e; + super(e.getComponent()); + Component comp = e.getComponent(); + peer = getComponentPeer(comp); + + create(peer); + connectSignals(peer); + cursor = comp.getCursor(); + } + + ComponentPeer getComponentPeer(Component c) + { + Component curr = c; + while (curr.getPeer() instanceof LightweightPeer) + curr = curr.getParent(); + + if (curr != null) + return curr.getPeer(); + return null; } public void startDrag(DragSourceContext context, Cursor c, Image i, Point p) throws InvalidDnDOperationException - { - // FIXME: Not Implemented + { + this.context = context; + + if (p == null) + p = new Point(); + + // FIXME: use proper DataFlavor, not "text/plain". + // Also, add check to determine if dragging. + + setCursor(c); + nativeStartDrag(i, p.x, p.y, context.getTrigger().getDragAction(), + "text/plain"); } public Cursor getCursor() { - // FIXME: Not Implemented - return null; + return cursor; } public void setCursor(Cursor c) throws InvalidDnDOperationException { - // FIXME: Not Implemented + if (c != null) + { + nativeSetCursor(c.getType()); + cursor = c; + } } public void transferablesFlavorsChanged() { - // FIXME: Not Implemented + // Nothing to do here. + } + + /** + * Called from native code. + */ + + public void dragEnter(int action, int modifiers) + { + context.dragEnter(new DragSourceDragEvent(context, action, + action + & context.getSourceActions(), + modifiers)); + } + + public void dragExit(int action, int x, int y) + { + context.dragExit(new DragSourceEvent(context, x, y)); + } + + public void dragDropEnd(int action, boolean success, int x, int y) + { + context.dragDropEnd(new DragSourceDropEvent(context, action, success, x, y)); + } + + public void dragMouseMoved(int action, int modifiers) + { + context.dragMouseMoved(new DragSourceDragEvent(context, + action, + action + & context.getSourceActions(), + modifiers)); + } + + public void dragOver(int action, int modifiers) + { + context.dragOver(new DragSourceDragEvent(context, action, + action + & context.getSourceActions(), + modifiers)); + } + + public void dragActionChanged(int newAction, int modifiers) + { + context.dropActionChanged(new DragSourceDragEvent(context, + newAction, + newAction + & context.getSourceActions(), + modifiers)); } } diff --git a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java index 421503e43..50cd95d41 100644 --- a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java +++ b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java @@ -38,6 +38,8 @@ exception statement from your version. */ package gnu.java.awt.dnd.peer.gtk; +import gnu.java.awt.peer.gtk.GtkGenericPeer; + import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DropTarget; @@ -45,9 +47,15 @@ import java.awt.dnd.InvalidDnDOperationException; import java.awt.dnd.peer.DropTargetContextPeer; public class GtkDropTargetContextPeer + extends GtkGenericPeer implements DropTargetContextPeer { + public GtkDropTargetContextPeer() + { + super(null); + } + public void setTargetActions(int actions) { // FIXME: Not Implemented diff --git a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java index d7ed26dae..88b75ad96 100644 --- a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java +++ b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java @@ -38,13 +38,21 @@ exception statement from your version. */ package gnu.java.awt.dnd.peer.gtk; +import gnu.java.awt.peer.gtk.GtkGenericPeer; + import java.awt.dnd.DropTarget; import java.awt.dnd.peer.DropTargetPeer; public class GtkDropTargetPeer + extends GtkGenericPeer implements DropTargetPeer { + public GtkDropTargetPeer() + { + super(null); + } + public void addDropTarget(DropTarget target) { // FIXME: Not Implemented diff --git a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java index d9d300d91..6a74eabc5 100644 --- a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java +++ b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java @@ -40,10 +40,8 @@ package gnu.java.awt.peer.gtk; import java.awt.Color; import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Image; -import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.font.GlyphVector; diff --git a/gnu/java/awt/peer/gtk/CairoSurface.java b/gnu/java/awt/peer/gtk/CairoSurface.java index 020d8eadd..78bc1e02d 100644 --- a/gnu/java/awt/peer/gtk/CairoSurface.java +++ b/gnu/java/awt/peer/gtk/CairoSurface.java @@ -38,27 +38,16 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.Graphics; -import java.awt.Color; -import java.awt.Image; import java.awt.Point; import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; -import java.io.File; -import java.io.IOException; import java.nio.ByteOrder; import java.util.Hashtable; -import java.util.Vector; -import java.io.ByteArrayOutputStream; -import java.io.BufferedInputStream; -import java.net.URL; -import gnu.classpath.Pointer; /** * CairoSurface - wraps a Cairo surface. @@ -186,42 +175,36 @@ public class CairoSurface extends DataBuffer int[] data = image.getPixels(); // Swap ordering from GdkPixbuf to Cairo - for(int i = 0; i < data.length; i++ ) + if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) + for (int i = 0; i < data.length; i++ ) { // On a big endian system we get a RRGGBBAA data array. - int alpha = (data[i] & 0xFF); + int alpha = data[i] & 0xFF; if( alpha == 0 ) // I do not know why we need this, but it works. data[i] = 0; else { - int r = (((data[i] & 0xFF000000) >> 24)); - int g = (((data[i] & 0x00FF0000) >> 16)); - int b = (((data[i] & 0x0000FF00) >> 8)); // Cairo needs a ARGB32 native array. - data[i] = (( alpha << 24 ) & 0xFF000000) - | (( r << 16 ) & 0x00FF0000) - | (( g << 8 ) & 0x0000FF00) - | ( b & 0x000000FF); + data[i] = (data[i] >>> 8) | (alpha << 24); } } - else + } + else + { + for (int i = 0; i < data.length; i++ ) { // On a little endian system we get a AABBGGRR data array. - int alpha = (data[i] & 0xFF000000) >> 24; + int alpha = data[i] & 0xFF000000; if( alpha == 0 ) // I do not know why we need this, but it works. data[i] = 0; else { - int b = (((data[i] & 0x00FF0000) >> 16)); - int g = (((data[i] & 0x0000FF00) >> 8)); - int r = ((data[i] & 0x000000FF)); + int b = (data[i] & 0xFF0000) >> 16; + int g = (data[i] & 0xFF00); + int r = (data[i] & 0xFF) << 16; // Cairo needs a ARGB32 native array. - data[i] = (( alpha << 24 ) & 0xFF000000) - | (( r << 16 ) & 0x00FF0000) - | (( g << 8 ) & 0x0000FF00) - | ( b & 0x000000FF); + data[i] = alpha | r | g | b; } } } diff --git a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java index 91f0b4981..7bd136c38 100644 --- a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java +++ b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java @@ -39,14 +39,9 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; import java.awt.Graphics; -import java.awt.Color; import java.awt.GraphicsEnvironment; -import java.awt.Image; -import java.awt.Point; -import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.geom.Rectangle2D; -import java.awt.image.*; /** * Implementation of Graphics2D on a Cairo surface. diff --git a/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java b/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java index 286fbeac0..2216d459a 100644 --- a/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java +++ b/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java @@ -39,17 +39,11 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; import java.awt.Image; -import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; import java.awt.image.RenderedImage; import java.awt.image.ImageObserver; diff --git a/gnu/java/awt/peer/gtk/GdkFontPeer.java b/gnu/java/awt/peer/gtk/GdkFontPeer.java index f5ed8a710..11635c354 100644 --- a/gnu/java/awt/peer/gtk/GdkFontPeer.java +++ b/gnu/java/awt/peer/gtk/GdkFontPeer.java @@ -38,7 +38,6 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import gnu.classpath.Configuration; import gnu.java.awt.peer.ClasspathFontPeer; import gnu.java.awt.font.opentype.NameDecoder; @@ -50,9 +49,7 @@ import java.awt.font.GlyphVector; import java.awt.font.GlyphMetrics; import java.awt.font.LineMetrics; import java.awt.geom.Rectangle2D; -import java.awt.geom.Point2D; import java.text.CharacterIterator; -import java.text.StringCharacterIterator; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; diff --git a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java index cd047f267..6d0a52b91 100644 --- a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java +++ b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -38,13 +38,10 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import gnu.classpath.Configuration; - import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; import java.awt.image.ImageConsumer; -import java.awt.image.ImageProducer; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.io.DataInput; diff --git a/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/gnu/java/awt/peer/gtk/GtkButtonPeer.java index 63d9cd487..f18db7af9 100644 --- a/gnu/java/awt/peer/gtk/GtkButtonPeer.java +++ b/gnu/java/awt/peer/gtk/GtkButtonPeer.java @@ -38,13 +38,8 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.AWTEvent; import java.awt.Button; -import java.awt.Component; -import java.awt.Point; import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; import java.awt.peer.ButtonPeer; // A composite widget. GtkButtons have transparent backgrounds. An diff --git a/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java index 1c5400c27..90d16c572 100644 --- a/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java +++ b/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java @@ -246,6 +246,9 @@ public class GtkCheckboxPeer extends GtkComponentPeer public void dispose () { + groupMap.clear(); + current_group = null; + currentState = false; super.dispose (); } } diff --git a/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java b/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java index fdc7d50c5..61df796dc 100644 --- a/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java +++ b/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java @@ -1,5 +1,5 @@ /* GtkClipboardNotifier.java -- Helper for announcing GtkSelection changes. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,8 +38,6 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.datatransfer.*; -import java.util.*; class GtkClipboardNotifier extends Thread { diff --git a/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java index dcbac1259..4686f12c1 100644 --- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -68,7 +68,6 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.event.PaintEvent; import java.awt.event.TextEvent; -import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; diff --git a/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/gnu/java/awt/peer/gtk/GtkContainerPeer.java index 06076e77f..541de3d82 100644 --- a/gnu/java/awt/peer/gtk/GtkContainerPeer.java +++ b/gnu/java/awt/peer/gtk/GtkContainerPeer.java @@ -42,10 +42,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Font; -import java.awt.Graphics; import java.awt.Insets; -import java.awt.Window; -import java.awt.peer.ComponentPeer; import java.awt.peer.ContainerPeer; public class GtkContainerPeer extends GtkComponentPeer diff --git a/gnu/java/awt/peer/gtk/GtkDialogPeer.java b/gnu/java/awt/peer/gtk/GtkDialogPeer.java index 3254f566d..13906544d 100644 --- a/gnu/java/awt/peer/gtk/GtkDialogPeer.java +++ b/gnu/java/awt/peer/gtk/GtkDialogPeer.java @@ -1,5 +1,5 @@ /* GtkDialogPeer.java -- Implements DialogPeer with GTK - Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2002, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,9 +39,6 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; import java.awt.Dialog; -import java.awt.Graphics; -import java.awt.Rectangle; -import java.awt.event.PaintEvent; import java.awt.peer.DialogPeer; public class GtkDialogPeer extends GtkWindowPeer diff --git a/gnu/java/awt/peer/gtk/GtkFramePeer.java b/gnu/java/awt/peer/gtk/GtkFramePeer.java index faac6d71d..bb6f8b3bb 100644 --- a/gnu/java/awt/peer/gtk/GtkFramePeer.java +++ b/gnu/java/awt/peer/gtk/GtkFramePeer.java @@ -39,11 +39,9 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; import java.awt.Frame; -import java.awt.Graphics; import java.awt.Image; import java.awt.MenuBar; import java.awt.Rectangle; -import java.awt.event.PaintEvent; import java.awt.peer.FramePeer; import java.awt.peer.MenuBarPeer; diff --git a/gnu/java/awt/peer/gtk/GtkImage.java b/gnu/java/awt/peer/gtk/GtkImage.java index ef96518a1..0fd98bbd7 100644 --- a/gnu/java/awt/peer/gtk/GtkImage.java +++ b/gnu/java/awt/peer/gtk/GtkImage.java @@ -39,12 +39,10 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; import java.awt.Graphics; -import java.awt.Color; import java.awt.Image; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; import java.awt.image.MemoryImageSource; -import java.awt.image.ImageConsumer; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; import java.io.File; diff --git a/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/gnu/java/awt/peer/gtk/GtkImageConsumer.java index 299f01dca..f1a74b8cc 100644 --- a/gnu/java/awt/peer/gtk/GtkImageConsumer.java +++ b/gnu/java/awt/peer/gtk/GtkImageConsumer.java @@ -1,5 +1,5 @@ /* GtkImageConsumer.java - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,16 +38,11 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.Graphics; -import java.awt.Image; import java.awt.image.ColorModel; -import java.awt.image.DirectColorModel; import java.awt.image.ImageConsumer; -import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; import java.awt.image.MemoryImageSource; import java.util.Hashtable; -import java.util.Vector; /** * Helper class to GtkImage. Sits and gathers pixels for a GtkImage and then diff --git a/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java index d203b437f..898f224f5 100644 --- a/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java +++ b/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java @@ -38,12 +38,9 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.Font; import java.awt.Menu; import java.awt.MenuBar; -import java.awt.MenuComponent; import java.awt.peer.MenuBarPeer; -import java.awt.peer.MenuPeer; public class GtkMenuBarPeer extends GtkMenuComponentPeer implements MenuBarPeer diff --git a/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java b/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java index 251bab233..ea523e953 100644 --- a/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java +++ b/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java @@ -38,13 +38,8 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.Font; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.MenuComponent; import java.awt.MenuItem; import java.awt.peer.MenuItemPeer; -import java.awt.peer.MenuPeer; public class GtkMenuItemPeer extends GtkMenuComponentPeer implements MenuItemPeer diff --git a/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java b/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java index 7f54da6d3..02bf84d4e 100644 --- a/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java +++ b/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java @@ -40,7 +40,6 @@ package gnu.java.awt.peer.gtk; import java.awt.Point; import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; import java.awt.Window; import java.awt.peer.MouseInfoPeer; diff --git a/gnu/java/awt/peer/gtk/GtkPanelPeer.java b/gnu/java/awt/peer/gtk/GtkPanelPeer.java index 51fe2bc8e..e0053f763 100644 --- a/gnu/java/awt/peer/gtk/GtkPanelPeer.java +++ b/gnu/java/awt/peer/gtk/GtkPanelPeer.java @@ -1,5 +1,5 @@ /* GtkPanelPeer.java -- Implements PanelPeer with GTK - Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,7 +41,6 @@ package gnu.java.awt.peer.gtk; import java.awt.AWTEvent; import java.awt.Panel; import java.awt.event.MouseEvent; -import java.awt.event.PaintEvent; import java.awt.peer.PanelPeer; public class GtkPanelPeer extends GtkContainerPeer diff --git a/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java b/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java index 525a910bc..4d66a3f50 100644 --- a/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java +++ b/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java @@ -40,7 +40,6 @@ package gnu.java.awt.peer.gtk; import java.awt.Component; import java.awt.Event; -import java.awt.MenuItem; import java.awt.Point; import java.awt.PopupMenu; import java.awt.peer.PopupMenuPeer; diff --git a/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java b/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java index 9b31a7390..e4147d36c 100644 --- a/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java +++ b/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java @@ -38,8 +38,6 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.Adjustable; -import java.awt.EventQueue; import java.awt.Scrollbar; import java.awt.event.AdjustmentEvent; import java.awt.peer.ScrollbarPeer; diff --git a/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/gnu/java/awt/peer/gtk/GtkWindowPeer.java index ca79a6d21..151094224 100644 --- a/gnu/java/awt/peer/gtk/GtkWindowPeer.java +++ b/gnu/java/awt/peer/gtk/GtkWindowPeer.java @@ -38,7 +38,6 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.AWTEvent; import java.awt.Component; import java.awt.Frame; import java.awt.Graphics; diff --git a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java index de67b316e..584965593 100644 --- a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java +++ b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java @@ -38,25 +38,11 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.Color; import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Image; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.font.GlyphVector; -import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferInt; -import java.awt.image.ColorModel; -import java.awt.image.DirectColorModel; -import java.awt.image.RenderedImage; import java.awt.image.ImageObserver; -import java.util.WeakHashMap; public class VolatileImageGraphics extends ComponentGraphics { diff --git a/gnu/java/awt/peer/x/XDialogPeer.java b/gnu/java/awt/peer/x/XDialogPeer.java new file mode 100644 index 000000000..45ad24d67 --- /dev/null +++ b/gnu/java/awt/peer/x/XDialogPeer.java @@ -0,0 +1,61 @@ +/* XDialogPeer.java -- The peer for AWT dialogs + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.awt.peer.x; + +import java.awt.Dialog; +import java.awt.peer.DialogPeer; + +public class XDialogPeer + extends XWindowPeer + implements DialogPeer +{ + + XDialogPeer(Dialog target) + { + super(target); + } + + public void setResizable(boolean resizeable) + { + } + + public void setTitle(String title) + { + } +} diff --git a/gnu/java/awt/peer/x/XEventPump.java b/gnu/java/awt/peer/x/XEventPump.java index bd1ef08ce..870edf379 100644 --- a/gnu/java/awt/peer/x/XEventPump.java +++ b/gnu/java/awt/peer/x/XEventPump.java @@ -207,9 +207,9 @@ public class XEventPump System.err.println("Setting size on AWT window: " + c.width() + ", " + c.height() + ", " + awtWindow.getWidth() + ", " + awtWindow.getHeight()); - ((XFramePeer) awtWindow.getPeer()).callback = true; + ((XWindowPeer) awtWindow.getPeer()).callback = true; awtWindow.setSize(c.width(), c.height()); - ((XFramePeer) awtWindow.getPeer()).callback = false; + ((XWindowPeer) awtWindow.getPeer()).callback = false; } break; case Expose.CODE: diff --git a/gnu/java/awt/peer/x/XFontPeer.java b/gnu/java/awt/peer/x/XFontPeer.java index 8a499db1a..fd293d8dd 100644 --- a/gnu/java/awt/peer/x/XFontPeer.java +++ b/gnu/java/awt/peer/x/XFontPeer.java @@ -694,7 +694,8 @@ public class XFontPeer } String protoType = fontProperties.getProperty(key.toString()); - return protoType.replaceFirst("%d", String.valueOf(size)); + int s = validSize(size); + return protoType.replaceFirst("%d", String.valueOf(s * 10)); } /** @@ -724,6 +725,31 @@ public class XFontPeer } /** + * Translates an arbitrary point size to a size that is typically available + * on an X server. These are the sizes 8, 10, 12, 14, 18 and 24. + * + * @param size the queried size + * @return the real available size + */ + private static final int validSize(int size) + { + int val; + if (size <= 9) + val = 8; + else if (size <= 11) + val = 10; + else if (size <= 13) + val = 12; + else if (size <= 17) + val = 14; + else if (size <= 23) + val = 18; + else + val = 24; + return val; + } + + /** * Returns the X Font reference. This lazily loads the font when first * requested. * diff --git a/gnu/java/awt/peer/x/XFramePeer.java b/gnu/java/awt/peer/x/XFramePeer.java index 1d34b1a81..439a2a7bb 100644 --- a/gnu/java/awt/peer/x/XFramePeer.java +++ b/gnu/java/awt/peer/x/XFramePeer.java @@ -46,56 +46,25 @@ import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; +import java.awt.MenuBar; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.PaintEvent; import java.awt.event.WindowEvent; +import java.awt.peer.FramePeer; import gnu.java.awt.peer.swing.SwingFramePeer; import gnu.x11.Window; import gnu.x11.event.Event; public class XFramePeer - extends SwingFramePeer + extends XWindowPeer + implements FramePeer { - private static int standardSelect = Event.BUTTON_PRESS_MASK - | Event.BUTTON_RELEASE_MASK - | Event.POINTER_MOTION_MASK - //| Event.RESIZE_REDIRECT_MASK - | Event.EXPOSURE_MASK - //| Event.PROPERTY_CHANGE_MASK - | Event.STRUCTURE_NOTIFY_MASK - | Event.KEY_PRESS_MASK - | Event.KEY_RELEASE_MASK - ; - - /** - * The X window. - */ - private Window xwindow; - - /** - * Indicates if we are in callback mode, that is when a property (like size) - * is changed in reponse to a request from the X server and doesn't need - * to be propagated back to the X server. - */ - boolean callback = false; - - public XFramePeer(Frame frame) + XFramePeer(Frame f) { - super(frame); - XGraphicsDevice dev = XToolkit.getDefaultDevice(); - - // TODO: Maybe initialize lazily in show(). - int x = Math.max(frame.getX(), 0); - int y = Math.max(frame.getY(), 0); - int w = Math.max(frame.getWidth(), 1); - int h = Math.max(frame.getHeight(), 1); - xwindow = new Window(dev.getDisplay().default_root, x, y, w, h); - xwindow.create(); - xwindow.select_input(standardSelect); - dev.getEventPump().registerWindow(xwindow, frame); + super(f); } public void setIconImage(Image image) @@ -104,6 +73,12 @@ public class XFramePeer throw new UnsupportedOperationException("Not yet implemented."); } + public void setMenuBar(MenuBar mb) + { + // TODO: Implement this. + throw new UnsupportedOperationException("Not yet implemented."); + } + public void setResizable(boolean resizable) { // TODO: Implement this. @@ -124,198 +99,42 @@ public class XFramePeer public void setState(int state) { - // FIXME: Implement this. + // TODO: Implement this. throw new UnsupportedOperationException("Not yet implemented."); } public void setMaximizedBounds(Rectangle r) { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public void setBoundsPrivate(int x, int y, int width, int height) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public void toBack() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public void toFront() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public void updateAlwaysOnTop() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public boolean requestWindowFocus() - { - // FIXME: Implement this. + // TODO: Implement this. throw new UnsupportedOperationException("Not yet implemented."); } - - public Point getLocationOnScreen() - { - return new Point(xwindow.x, xwindow.y); - } - + /** - * Returns a XGraphics suitable for drawing on this frame. - * - * @return a XGraphics suitable for drawing on this frame + * Check if this frame peer supports being restacked. + * + * @return true if this frame peer can be restacked, + * false otherwise + * @since 1.5 */ - public Graphics getGraphics() - { - return new XGraphics(xwindow); - } - - public Image createImage(int w, int h) + public boolean isRestackSupported() { - return new XImage(w, h); - } - - /** - * Sets the visibility state of the component. This is called by - * {@link Component#setVisible(boolean)}. - * - * This is implemented to call setVisible() on the Swing component. - * - * @param visible <code>true</code> to make the component visible, - * <code>false</code> to make it invisible - */ - public void setVisible(boolean visible) - { - if (visible) - show(); - else - hide(); - } - - /** - * Makes the component visible. This is called by {@link Component#show()}. - * - * This is implemented to call setVisible(true) on the Swing component. - */ - public void show() - { -// // Prevent ResizeRedirect events. -// //xwindow.select_input(noResizeRedirectSelect); -// Window.Attributes atts = new Window.Attributes(); -// atts.set_override_redirect(true); -// xwindow.change_attributes(atts); - - // Prevent ResizeRedirect events. - //xwindow.select_input(Event.NO_EVENT_MASK); - //xwindow.select_input(noResizeRedirectSelect); - - xwindow.map(); - EventQueue eq = XToolkit.getDefaultToolkit().getSystemEventQueue(); - java.awt.Window w = (java.awt.Window) super.awtComponent; - eq.postEvent(new WindowEvent(w, WindowEvent.WINDOW_OPENED)); - eq.postEvent(new PaintEvent(w, PaintEvent.PAINT, - new Rectangle(0, 0, w.getWidth(), - w.getHeight()))); - -// // Reset input selection. -// atts.set_override_redirect(false); -// xwindow.change_attributes(atts); - } - - /** - * Makes the component invisible. This is called from - * {@link Component#hide()}. - * - * This is implemented to call setVisible(false) on the Swing component. - */ - public void hide() - { - xwindow.unmap(); - } - - /** - * Notifies the peer that the bounds of this component have changed. This - * is called by {@link Component#reshape(int, int, int, int)}. - * - * This is implemented to call setBounds() on the Swing component. - * - * @param x the X coordinate of the upper left corner of the component - * @param y the Y coordinate of the upper left corner of the component - * @param width the width of the component - * @param height the height of the component - */ - public void reshape(int x, int y, int width, int height) - { -// if (callback) -// return; - - // Prevent ResizeRedirect events. -// //xwindow.select_input(noResizeRedirectSelect); -// Window.Attributes atts = new Window.Attributes(); -// atts.set_override_redirect(true); -// xwindow.change_attributes(atts); - - // Need to substract insets because AWT size is including insets, - // and X size is excuding insets. - Insets i = insets(); - xwindow.move_resize(x - i.left, y - i.right, width - i.left - i.right, - height - i.top - i.bottom); - - // Reset input selection. -// atts = new Window.Attributes(); -// atts.set_override_redirect(false); -// xwindow.change_attributes(atts); - } - - public Insets insets() - { - Insets i = new Insets(0, 0, 0, 0); -// Window.GeometryReply g = xwindow.geometry(); -// int b = g.border_width(); -// Insets i = new Insets(b, b, b, b); -// Window.WMSizeHints wmSize = xwindow.wm_normal_hints(); -// if (wmSize != null) -// { -// i.left = wmSize.x() - g.x(); -// i.right = wmSize.width() - g.width() - i.left ; -// i.top = wmSize.y() - g.y(); -// i.bottom = wmSize.height() - g.height() - i.top; -// } -// System.err.println("insets: " + i); - return i; - } - - /** - * Returns the font metrics for the specified font. - * - * @return the font metrics for the specified font - */ - public FontMetrics getFontMetrics(Font font) - { - XFontPeer fontPeer = (XFontPeer) font.getPeer(); - return fontPeer.getFontMetrics(font); + // TODO: Implement this. + throw new UnsupportedOperationException("Not yet implemented."); } - + /** - * Unregisters the window in the event pump when it is closed. + * Sets the bounds of this frame peer. + * + * @param x the new x co-ordinate + * @param y the new y co-ordinate + * @param width the new width + * @param height the new height + * @since 1.5 */ - protected void finalize() + public void setBoundsPrivate(int x, int y, int width, int height) { - XGraphicsDevice dev = XToolkit.getDefaultDevice(); - dev.getEventPump().unregisterWindow(xwindow); + // TODO: Implement this. + throw new UnsupportedOperationException("Not yet implemented."); } - public Rectangle getBounds() - { - return new Rectangle(xwindow.x, xwindow.y, xwindow.width, xwindow.height); - } } diff --git a/gnu/java/awt/peer/x/XGraphics.java b/gnu/java/awt/peer/x/XGraphics.java index 81168797c..134d7d330 100644 --- a/gnu/java/awt/peer/x/XGraphics.java +++ b/gnu/java/awt/peer/x/XGraphics.java @@ -38,40 +38,33 @@ exception statement from your version. */ package gnu.java.awt.peer.x; +import gnu.x11.Colormap; +import gnu.x11.Data; +import gnu.x11.Display; import gnu.x11.Drawable; import gnu.x11.GC; import gnu.x11.Pixmap; import gnu.x11.Point; +import gnu.x11.image.ZPixmap; import java.awt.AWTError; import java.awt.Color; -import java.awt.Composite; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; import java.awt.Image; -import java.awt.Paint; import java.awt.Rectangle; -import java.awt.RenderingHints; import java.awt.Shape; -import java.awt.Stroke; -import java.awt.RenderingHints.Key; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.geom.AffineTransform; +import java.awt.Toolkit; +import java.awt.Transparency; import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; -import java.awt.image.RenderedImage; -import java.awt.image.renderable.RenderableImage; import java.text.AttributedCharacterIterator; -import java.util.Map; +import java.util.HashMap; public class XGraphics - extends Graphics2D + extends Graphics implements Cloneable { @@ -111,6 +104,11 @@ public class XGraphics */ private boolean disposed = false; + // TODO: Workaround for limitation in current Escher. + private Pixmap.Format pixmapFormat; + private int imageByteOrder; + private int pixelByteCount; + /** * Creates a new XGraphics on the specified X Drawable. * @@ -123,6 +121,11 @@ public class XGraphics translateX = 0; translateY = 0; clip = new Rectangle(0, 0, d.width, d.height); + + Display display = xdrawable.display; + pixmapFormat = display.default_pixmap_format; + imageByteOrder = display.image_byte_order; + pixelByteCount = pixmapFormat.bits_per_pixel () / 8; } /** @@ -147,7 +150,6 @@ public class XGraphics { clip.x -= x; clip.y -= y; - setClip(clip); } } @@ -171,7 +173,18 @@ public class XGraphics { if (c != null) { - xgc.set_foreground(c.getRGB()); + XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit(); + HashMap colorMap = tk.colorMap; + gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c); + if (col == null) + { + Colormap map = xdrawable.display.default_colormap; + col = map.alloc_color (c.getRed() * 256, + c.getGreen() * 256, + c.getBlue() * 256); + colorMap.put(c, col); + } + xgc.set_foreground(col); foreground = c; } } @@ -257,7 +270,7 @@ public class XGraphics computeIntersection(x, y, width, height, clip); } // Update the X clip setting. - setClip(clip.x, clip.y, clip.width, clip.height); + setXClip(clip.x, clip.y, clip.width, clip.height); } /** @@ -282,9 +295,19 @@ public class XGraphics } else { - hit = clip.intersects(x, y, w, h); + // It's easier to determine if the rectangle lies outside the clip, + // so we determine that and reverse the result (if it's not completely + // outside, it most likely hits the clip rectangle). + int x2 = x + w; + int y2 = y + h; + int clipX2 = clip.x + clip.width; + int clipY2 = clip.y + clip.height; + boolean outside = (x < clip.x && x2 < clip.x) // Left. + || (x > clipX2 && x2 > clipX2) // Right. + || (y < clip.y && y2 < clip.y) // Top. + || (y > clipY2 && y2 > clipY2); // Bottom. + hit = ! outside; } - //System.err.println("hitClip: " + hit); return hit; } @@ -294,10 +317,23 @@ public class XGraphics clip.setBounds(x, y, width, height); else clip = new Rectangle(x, y, width, height); + setXClip(clip.x, clip.y, clip.width, clip.height); + } + /** + * Sets the clip on the X server GC. The coordinates are not yet translated, + * this will be performed by the X server. + * + * @param x the clip, X coordinate + * @param y the clip, Y coordinate + * @param w the clip, width + * @param h the clip, height + */ + private void setXClip(int x, int y, int w, int h) + { gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] { - new gnu.x11.Rectangle(x, y, width, height) }; - xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.UN_SORTED); + new gnu.x11.Rectangle(x, y, w, h) }; + xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.YX_BANDED); } public Shape getClip() @@ -309,33 +345,44 @@ public class XGraphics /** * Sets the current clip. * - * @param clip the clip to set + * @param c the clip to set */ - public void setClip(Shape clip) + public void setClip(Shape c) { - if (clip != null) + if (c != null) { Rectangle b; - if (clip instanceof Rectangle) + if (c instanceof Rectangle) { - b = (Rectangle) clip; + b = (Rectangle) c; } else { - b = clip.getBounds(); + b = c.getBounds(); } - setClip(b.x, b.y, b.width, b.height); + clip.setBounds(b); + setXClip(b.x, b.y, b.width, b.height); } else { - setClip(0, 0, xdrawable.width, xdrawable.height); + clip.setBounds(0, 0, xdrawable.width, xdrawable.height); + setXClip(0, 0, xdrawable.width, xdrawable.height); } } public void copyArea(int x, int y, int width, int height, int dx, int dy) { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); + // Clip and translate src rectangle. + int srcX = Math.min(Math.max(x, clip.x), clip.x + clip.width) + + translateX; + int srcY = Math.min(Math.max(y, clip.y), clip.y + clip.height) + + translateY; + int srcWidth = Math.min(Math.max(x + width, clip.x), + clip.x + clip.width) - x; + int srcHeight = Math.min(Math.max(y + height, clip.y), + clip.y + clip.height) - y; + xdrawable.copy_area(xdrawable, xgc, srcX, srcY, srcWidth, srcHeight, + srcX + dx, srcY + dy); } /** @@ -498,32 +545,51 @@ public class XGraphics xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height, x + translateX, y + translateY); } -// else if (image instanceof BufferedImage) -// { -// BufferedImage bufferedImage = (BufferedImage) image; -// Raster raster = bufferedImage.getData(); -// int w = bufferedImage.getWidth(); -// int h = bufferedImage.getHeight(); -// // Push data to X server. -// ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h, -// xdrawable.display.default_pixmap_format); -// System.err.println("data buffer length: " + zPixmap.data.length); -// int[] pixel = new int[4]; -// for (int tx = 0; tx < w; tx++) -// { -// for (int ty = 0; ty < h; ty++) -// { -// pixel = raster.getPixel(tx, ty, pixel); -//// System.err.print("r: " + pixel[0]); -//// System.err.print(", g: " + pixel[1]); -//// System.err.println(", b: " + pixel[2]); -// zPixmap.set_red(tx, ty, pixel[0]); -// zPixmap.set_green(tx, ty, pixel[1]); -// zPixmap.set_blue(tx, ty, pixel[2]); -// } -// } -// xdrawable.put_image(xgc, zPixmap, x, y); -// } + else if (image instanceof BufferedImage + && ((BufferedImage) image).getTransparency() != Transparency.OPAQUE) + { + BufferedImage bi = (BufferedImage) image; + int width = bi.getWidth(); + int height = bi.getHeight(); + Data img = xdrawable.image(x + translateX, y + translateY, + width, height, 0xFFFFFFFF, 2); + + // Compute line byte count. + int lineBitCount = width * pixmapFormat.bits_per_pixel (); + int rem = lineBitCount % pixmapFormat.scanline_pad (); + int linePadCount = lineBitCount / pixmapFormat.scanline_pad () + + (rem == 0 ? 0 : 1); + int lineByteCount = linePadCount * pixmapFormat.scanline_pad () / 8; + + // Composite source and destination pixel data. + int[] trgb = new int[3]; // The device rgb pixels. + for (int yy = 0; yy < height; yy++) + { + for (int xx = 0; xx < width; xx++) + { + getRGB(xx, yy, img, trgb, lineByteCount); + int srgb = bi.getRGB(xx, yy); + float alpha = ((srgb >> 24) & 0xff) / 256F; + float tAlpha = 1.F - alpha; + int red = (srgb >> 16) & 0xFF; + int green = (srgb >> 8) & 0xFF; + int blue = (srgb) & 0xFF; + trgb[0] = (int) (trgb[0] * tAlpha + red * alpha); + trgb[1] = (int) (trgb[1] * tAlpha + green * alpha); + trgb[2] = (int) (trgb[2] * tAlpha + blue * alpha); + setRGB(xx, yy, img, trgb, lineByteCount); + } + } + + // Now we have the transparent image composited onto the target + // Image, now we only must copy it to the Drawable. + ZPixmap pm = new ZPixmap(xdrawable.display); + pm.width = width; + pm.height = height; + pm.init(); + System.arraycopy(img.data, 32, pm.data, 0, img.data.length - 32); + xdrawable.put_image(xgc, pm, x + translateX, y + translateY); + } else { // Pre-render the image into an XImage. @@ -538,6 +604,59 @@ public class XGraphics return true; } + /** + * Helper method to work around limitation in the current Escher impl. + * + * @param x the x position + * @param y the y position + * @param img the image data + * @param rgb an 3-size array that holds the rgb values on method exit + */ + private void getRGB(int x, int y, Data img, int[] rgb, int lineByteCount) + { + // TODO: Does this also work on non-RGB devices? + int i = y * lineByteCount + pixelByteCount * x; + if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST) + {//if (i >= 5716-33) System.err.println("lbc: " + lineByteCount + ", " + pixelByteCount); + rgb[2] = img.data[32 + i]; + rgb[1] = img.data[32 + i + 1]; + rgb[0] = img.data[32 + i + 2]; + } + else + { // MSB_FIRST + rgb[0] = img.data[32 + i]; + rgb[1] = img.data[32 + i + 1]; + rgb[2] = img.data[32 + i + 2]; + } + + } + + /** + * Helper method to work around limitation in the current Escher impl. + * + * @param x the x position + * @param y the y position + * @param img the image data + * @param rgb an 3-size array that holds the rgb values on method exit + */ + private void setRGB(int x, int y, Data img, int[] rgb, int lineByteCount) + { + // TODO: Does this also work on non-RGB devices? + int i = y * lineByteCount + pixelByteCount * x; + if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST) + { + img.data[32 + i] = (byte) rgb[2]; + img.data[32 + i + 1] = (byte) rgb[1]; + img.data[32 + i + 2] = (byte) rgb[0]; + } + else + { // MSB_FIRST + img.data[32 + i] = (byte) rgb[0]; + img.data[32 + i + 1] = (byte) rgb[1]; + img.data[32 + i + 2] = (byte) rgb[2]; + } + } + public boolean drawImage(Image image, int x, int y, int width, int height, ImageObserver observer) { @@ -563,16 +682,41 @@ public class XGraphics int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); + return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, + observer); } public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); + + // FIXME: What to do with bgcolor? + + // Scale the image. + int sw = image.getWidth(observer); + int sh = image.getHeight(observer); + double scaleX = Math.abs(dx2 - dx1) / (double) Math.abs(sx2 - sx1); + double scaleY = Math.abs(dy2 - dy1) / (double) Math.abs(sy2 - sy1); + Image scaled = image.getScaledInstance((int) (scaleX * sw), + (int) (scaleY * sh), + Image.SCALE_FAST); + + // Scaled source coordinates. + int sx1s = (int) (scaleX * Math.min(sx1, sx2)); + int sx2s = (int) (scaleX * Math.max(sx1, sx2)); + + // Temporarily clip to the target rectangle. + Rectangle old = clip; + clipRect(dx1, dy1, dx2 - dx1, dy2 - dy1); + + // Draw scaled image. + boolean res = drawImage(scaled, dx1 - sx1s, dy1 - sx2s, observer); + + // Reset clip. + setClip(old); + + return res; } /** @@ -580,221 +724,14 @@ public class XGraphics */ public void dispose() { - xdrawable.display.flush(); if (! disposed) { xgc.free(); + xdrawable.display.flush(); disposed = true; } } - // Additional Graphics2D methods. - - public void draw(Shape shape) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean drawImage(Image image, AffineTransform xform, ImageObserver obs) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void drawRenderedImage(RenderedImage image, AffineTransform xform) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void drawRenderableImage(RenderableImage image, AffineTransform xform) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void drawString(String text, float x, float y) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void drawString(AttributedCharacterIterator iterator, float x, float y) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void fill(Shape shape) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean hit(Rectangle rect, Shape text, boolean onStroke) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public GraphicsConfiguration getDeviceConfiguration() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setComposite(Composite comp) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setPaint(Paint paint) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setStroke(Stroke stroke) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setRenderingHint(Key hintKey, Object hintValue) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public Object getRenderingHint(Key hintKey) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setRenderingHints(Map hints) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void addRenderingHints(Map hints) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public RenderingHints getRenderingHints() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void translate(double tx, double ty) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void rotate(double theta) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void rotate(double theta, double x, double y) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void scale(double scaleX, double scaleY) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void shear(double shearX, double shearY) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void transform(AffineTransform Tx) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setTransform(AffineTransform Tx) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public AffineTransform getTransform() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public Paint getPaint() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public Composite getComposite() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setBackground(Color color) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public Color getBackground() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public Stroke getStroke() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void clip(Shape s) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public FontRenderContext getFontRenderContext() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void drawGlyphVector(GlyphVector g, float x, float y) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - // Additional helper methods. /** @@ -806,18 +743,18 @@ public class XGraphics { XGraphics copy = (XGraphics) super.clone(); copy.xgc = xgc.copy(); - - // Save the original clip. if (clip != null) - copy.clip = new Rectangle(clip); + { + copy.clip = new Rectangle(clip); + copy.setXClip(clip.x, clip.y, clip.width, clip.height); + } return copy; } catch (CloneNotSupportedException ex) { - AWTError err = new AWTError("Error while cloning XGraphics"); - err.initCause(ex); - throw err; + assert false; } + return null; } /** diff --git a/gnu/java/awt/peer/x/XGraphicsEnvironment.java b/gnu/java/awt/peer/x/XGraphicsEnvironment.java index 707b44c38..65383a6cb 100644 --- a/gnu/java/awt/peer/x/XGraphicsEnvironment.java +++ b/gnu/java/awt/peer/x/XGraphicsEnvironment.java @@ -80,7 +80,7 @@ public class XGraphicsEnvironment * environment. If there is no configuration, then there is one * default device initialized with the local main X device. */ - XGraphicsEnvironment() + public XGraphicsEnvironment() { // Initiliaze the devices. Properties props = new Properties(); diff --git a/gnu/java/awt/peer/x/XImage.java b/gnu/java/awt/peer/x/XImage.java index 28bc6b90a..b9e993628 100644 --- a/gnu/java/awt/peer/x/XImage.java +++ b/gnu/java/awt/peer/x/XImage.java @@ -43,9 +43,9 @@ import gnu.x11.Pixmap; import java.awt.Graphics; import java.awt.GraphicsEnvironment; import java.awt.Image; -import java.awt.Toolkit; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; +import java.util.Hashtable; public class XImage extends Image @@ -53,10 +53,12 @@ public class XImage Pixmap pixmap; + private Hashtable properties; + XImage(int w, int h) { - XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit(); - GraphicsEnvironment env = tk.getLocalGraphicsEnvironment(); + GraphicsEnvironment env = + GraphicsEnvironment.getLocalGraphicsEnvironment(); XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice(); pixmap = new Pixmap(dev.getDisplay(), w, h); } @@ -90,8 +92,10 @@ public class XImage public Object getProperty(String name, ImageObserver observer) { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); + Object val = null; + if (properties != null) + val = properties.get(val); + return val; } public void flush() diff --git a/gnu/java/awt/peer/x/XToolkit.java b/gnu/java/awt/peer/x/XToolkit.java index 343a8f44f..a286fd6f0 100644 --- a/gnu/java/awt/peer/x/XToolkit.java +++ b/gnu/java/awt/peer/x/XToolkit.java @@ -67,6 +67,7 @@ import java.awt.ScrollPane; import java.awt.Scrollbar; import java.awt.TextArea; import java.awt.TextField; +import java.awt.Transparency; import java.awt.Window; import java.awt.datatransfer.Clipboard; import java.awt.dnd.DragGestureEvent; @@ -131,7 +132,10 @@ public class XToolkit */ static boolean DEBUG = false; - private XGraphicsEnvironment env; + /** + * Maps AWT colors to X colors. + */ + HashMap colorMap = new HashMap(); /** * The system event queue. @@ -162,9 +166,7 @@ public class XToolkit public GraphicsEnvironment getLocalGraphicsEnvironment() { - if (env == null) - env = new XGraphicsEnvironment(); - return env; + return new XGraphicsEnvironment(); } /** @@ -289,8 +291,7 @@ public class XToolkit protected DialogPeer createDialog(Dialog target) { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); + return new XDialogPeer(target); } protected MenuBarPeer createMenuBar(MenuBar target) @@ -502,8 +503,10 @@ public class XToolkit public Image createImage(ImageProducer producer) { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); + ImageConverter conv = new ImageConverter(); + producer.startProduction(conv); + Image image = conv.getXImage(); + return image; } public Image createImage(byte[] data, int offset, int len) @@ -526,12 +529,16 @@ public class XToolkit { Image image; BufferedImage buffered = ImageIO.read(i); - if (buffered != null) + // If the bufferedimage is opaque, then we can copy it over to an + // X Pixmap for faster drawing. + if (buffered != null && buffered.getTransparency() == Transparency.OPAQUE) { - ImageConverter conv = new ImageConverter(); ImageProducer source = buffered.getSource(); - source.startProduction(conv); - image = conv.getXImage(); + image = createImage(source); + } + else if (buffered != null) + { + image = buffered; } else { diff --git a/gnu/java/awt/peer/x/XWindowPeer.java b/gnu/java/awt/peer/x/XWindowPeer.java index f4815ce7f..28cc5a5ed 100644 --- a/gnu/java/awt/peer/x/XWindowPeer.java +++ b/gnu/java/awt/peer/x/XWindowPeer.java @@ -85,7 +85,6 @@ public class XWindowPeer XWindowPeer(java.awt.Window window) { super(window); - System.err.println("new XWindowPeer"); XGraphicsDevice dev = XToolkit.getDefaultDevice(); // TODO: Maybe initialize lazily in show(). diff --git a/gnu/java/lang/management/MemoryMXBeanImpl.java b/gnu/java/lang/management/MemoryMXBeanImpl.java index 614ae18b8..6890130d4 100644 --- a/gnu/java/lang/management/MemoryMXBeanImpl.java +++ b/gnu/java/lang/management/MemoryMXBeanImpl.java @@ -38,8 +38,27 @@ exception statement from your version. */ package gnu.java.lang.management; import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryNotificationInfo; import java.lang.management.MemoryUsage; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.Notification; +import javax.management.NotificationEmitter; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; + /** * Provides access to information about the memory * management of the current invocation of the virtual @@ -51,9 +70,63 @@ import java.lang.management.MemoryUsage; */ public final class MemoryMXBeanImpl extends BeanImpl - implements MemoryMXBean + implements MemoryMXBean, NotificationEmitter { + private List listeners; + + private long notificationCount; + + public static CompositeType notifType; + + public static CompositeType usageType; + + static + { + try + { + CompositeType usageType = + new CompositeType(MemoryUsage.class.getName(), + "Describes the usage levels of a pool", + new String[] { "init", "used", + "committed", "max" + }, + new String[] { "Initial level", + "Used level", + "Committed level", + "Maximum level" + }, + new OpenType[] { + SimpleType.LONG, SimpleType.LONG, + SimpleType.LONG, SimpleType.LONG + }); + CompositeType notifType = + new CompositeType(MemoryNotificationInfo.class.getName(), + "Provides the notification info on memory usage", + new String[] { "poolName", "usage", "count" }, + new String[] { "Name of the memory pool", + "Usage level of the memory pool", + "Number of times the threshold " + + "has been crossed" + }, + new OpenType[] { + SimpleType.STRING, usageType, SimpleType.LONG + }); + } + catch (OpenDataException e) + { + throw new IllegalStateException("Something went wrong in creating " + + "the composite data types.", e); + } + } + + + public MemoryMXBeanImpl() + { + listeners = new ArrayList(); + notificationCount = 0; + } + public void gc() { System.gc(); @@ -85,4 +158,155 @@ public final class MemoryMXBeanImpl VMMemoryMXBeanImpl.setVerbose(verbose); } + private class ListenerData + { + private NotificationListener listener; + private NotificationFilter filter; + private Object passback; + + public ListenerData(NotificationListener listener, + NotificationFilter filter, Object passback) + { + this.listener = listener; + this.filter = filter; + this.passback = passback; + } + + public NotificationListener getListener() + { + return listener; + } + + public NotificationFilter getFilter() + { + return filter; + } + + public Object getPassback() + { + return passback; + } + + public boolean equals(Object obj) + { + if (obj instanceof ListenerData) + { + ListenerData data = (ListenerData) obj; + return (data.getListener() == listener && + data.getFilter() == filter && + data.getPassback() == passback); + } + return false; + } + + } + + public void addNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object passback) + { + if (listener == null) + throw new IllegalArgumentException("Null listener added to bean."); + listeners.add(new ListenerData(listener, filter, passback)); + } + + public MBeanNotificationInfo[] getNotificationInfo() + { + return new MBeanNotificationInfo[] + { + new MBeanNotificationInfo(new String[] + { + MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED, + MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED + }, + Notification.class.getName(), + "Memory Usage Notifications") + }; + } + + public void removeNotificationListener(NotificationListener listener) + throws ListenerNotFoundException + { + Iterator it = listeners.iterator(); + boolean foundOne = false; + while (it.hasNext()) + { + ListenerData data = (ListenerData) it.next(); + if (data.getListener() == listener) + { + it.remove(); + foundOne = true; + } + } + if (!foundOne) + throw new ListenerNotFoundException("The specified listener, " + listener + + "is not registered with this bean."); + } + + public void removeNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object passback) + throws ListenerNotFoundException + { + if (!(listeners.remove(new ListenerData(listener, filter, passback)))) + { + throw new ListenerNotFoundException("The specified listener, " + listener + + " with filter " + filter + + "and passback " + passback + + ", is not registered with this bean."); + } + } + + void fireNotification(String type, String poolName, long init, long used, + long committed, long max, long count) + { + Notification notif = new Notification(type, this, notificationCount); + MemoryUsage usage = new MemoryUsage(init, used, committed, max); + CompositeData data; + try + { + data = new CompositeDataSupport(notifType, + new String[] { + "poolName", "usage", "count" + }, + new Object[] { + poolName, usage, Long.valueOf(count) + }); + } + catch (OpenDataException e) + { + throw new IllegalStateException("Something went wrong in creating " + + "the composite data instance.", e); + } + notif.setUserData(data); + Iterator it = listeners.iterator(); + while (it.hasNext()) + { + ListenerData ldata = (ListenerData) it.next(); + NotificationFilter filter = ldata.getFilter(); + if (filter == null || filter.isNotificationEnabled(notif)) + ldata.getListener().handleNotification(notif, ldata.getPassback()); + } + ++notificationCount; + } + + void fireThresholdExceededNotification(String poolName, long init, + long used, long committed, + long max, long count) + { + fireNotification(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED, + poolName, init, used, committed, max, count); + } + + void fireCollectionThresholdExceededNotification(String poolName, + long init, + long used, + long committed, + long max, + long count) + { + fireNotification(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED, + poolName, init, used, committed, max, count); + } + } diff --git a/gnu/java/lang/management/MemoryPoolMXBeanImpl.java b/gnu/java/lang/management/MemoryPoolMXBeanImpl.java index af718e3ff..9554aae00 100644 --- a/gnu/java/lang/management/MemoryPoolMXBeanImpl.java +++ b/gnu/java/lang/management/MemoryPoolMXBeanImpl.java @@ -125,6 +125,11 @@ public final class MemoryPoolMXBeanImpl return null; } + public String getType() + { + return VMMemoryPoolMXBeanImpl.getType(name); + } + public MemoryUsage getUsage() { if (isValid()) diff --git a/gnu/java/security/util/IntegerUtil.java b/gnu/java/security/util/IntegerUtil.java new file mode 100644 index 000000000..f07130808 --- /dev/null +++ b/gnu/java/security/util/IntegerUtil.java @@ -0,0 +1,109 @@ +/* IntegerUtil.java -- JDK 5 Integer methods with 1.4 API + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.security.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Utility class which offers Integer related methods found in RI's version 5 + * but written with RI's 1.4 API. + */ +public abstract class IntegerUtil +{ + /** Maximum size of our cache of constructed Integers. */ + private static final int CACHE_SIZE = 100; + /** LRU (Least Recently Used) cache, of the last accessed 100 Integers. */ + private static final Map cache = new LinkedHashMap(CACHE_SIZE + 1, 0.75F, true) + { + public boolean removeEldestEntry(Map.Entry entry) + { + return size() > CACHE_SIZE; + } + }; + + /** Trivial private constructor to enforce Singleton usage. */ + private IntegerUtil() + { + super(); + } + + /** + * Similar to {@link Integer#valueOf(String)} except it caches the result in + * a local LRU cache of 100 elements, organized by access order. + * <p> + * This method MUST be used in the gnu.java.security and gnu.javax.crypto + * packages to ensure they would work with a version 1.4 only of the Java + * class library API. + * + * @param aString a string representation of an integer. + * @return the {@link Integer} object representing the designated string. + */ + public static final Integer valueOf(String aString) + { + Integer result; + synchronized (cache) + { + result = (Integer) cache.get(aString); + if (result == null) + { + result = Integer.valueOf(aString); + cache.put(aString, result); + } + } + return result; + } + + /** + * Simulates the <code>valueOf(int)</code> method found in {@link Integer} of + * the RI's version 1.5 using a local LRU cache of 100 elements, organized by + * access order. + * <p> + * This method MUST be used in the gnu.java.security and gnu.javax.crypto + * packages to ensure they would work with a version 1.4 only of the Java + * class library API. + * + * @param anInt a decimal integer. + * @return the {@link Integer} object representing the designated primitive. + */ + public static final Integer valueOf(int anInt) + { + return valueOf(Integer.toString(anInt, 10)); + } +} diff --git a/gnu/java/util/regex/RE.java b/gnu/java/util/regex/RE.java index cd12aab8f..24dd4ef3f 100644 --- a/gnu/java/util/regex/RE.java +++ b/gnu/java/util/regex/RE.java @@ -130,7 +130,7 @@ public class RE extends REToken { private static final String VERSION = "1.1.5-dev"; // The localized strings are kept in a separate file - private static ResourceBundle messages = PropertyResourceBundle.getBundle("gnu/regexp/MessagesBundle", Locale.getDefault()); + private static ResourceBundle messages = PropertyResourceBundle.getBundle("gnu/java/util/regex/MessagesBundle", Locale.getDefault()); // These are, respectively, the first and last tokens in our linked list // If there is only one token, firstToken == lastToken diff --git a/gnu/javax/crypto/cipher/TripleDES.java b/gnu/javax/crypto/cipher/TripleDES.java index 7aeb4ea96..1e98bfc83 100644 --- a/gnu/javax/crypto/cipher/TripleDES.java +++ b/gnu/javax/crypto/cipher/TripleDES.java @@ -40,17 +40,21 @@ package gnu.javax.crypto.cipher; import gnu.java.security.Registry; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.security.InvalidKeyException; /** * Triple-DES, 3DES, or DESede is a <i>combined cipher</i> that uses three - * iterations of the Data Encryption Standard cipher to improve the security (at - * the cost of speed) of plain DES. + * iterations of the Data Encryption Standard cipher to theoretically improve + * the security of plain DES, at the cost of speed. * <p> - * Triple-DES runs the DES algorithm three times with three independent 56 bit - * keys. To encrypt: + * Triple-DES runs the DES algorithm three times with one, two or three + * independent 56-bit (DES) keys. When used with one DES key, the cipher behaves + * exactly like a (slower) DES. + * <p> + * To encrypt: * <blockquote><i>C<sub>i</sub> = E<sub>k3</sub> ( E<sub>k2</sub><sup>-1</sup> ( * E<sub>k1</sub> ( P<sub>i</sub> )))</i> * </blockquote> @@ -75,10 +79,8 @@ public class TripleDES { /** Triple-DES only operates on 64 bit blocks. */ public static final int BLOCK_SIZE = 8; - - /** Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */ + /** By default, Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */ public static final int KEY_SIZE = 24; - /** The underlying DES instance. */ private DES des; @@ -92,21 +94,45 @@ public class TripleDES } /** - * Transform a key so it will be parity adjusted. + * Convenience method which calls the method with same name and three + * arguments, passing <code>3</code> as the value of the first parameter. * * @param kb The key bytes to adjust. * @param offset The starting offset into the key bytes. - * @see DES#adjustParity(byte[],int) */ public static void adjustParity(byte[] kb, int offset) { + adjustParity(3, kb, offset); + } + + /** + * Adjusts, in-situ, the parity of the designated bytes, so they can be used + * as DES keys for a 3-DES 1-, 2- or 3-key cipher. + * + * @param keyCount the number of independent DES keys. Can be either + * <code>1</code>, <code>2</code> or <code>3</code>. Any other value + * will cause an {@link IllegalArgumentException} to be raised. + * @param kb the array containing the key bytes to adjust. MUST have at least + * <code>8 * keyCount</code> bytes starting at offset position + * <code>offset</code>, otherwise an + * {@link ArrayIndexOutOfBoundsException} will be raised. + * @param offset the starting offset into the array. + * @see DES#adjustParity(byte[],int) + */ + public static void adjustParity(int keyCount, byte[] kb, int offset) + { + if (keyCount < 1 || keyCount > 3) + throw new IllegalArgumentException("Invalid keyCount value: " + keyCount); DES.adjustParity(kb, offset); - DES.adjustParity(kb, offset + 8); - DES.adjustParity(kb, offset + 16); + if (keyCount > 1) + DES.adjustParity(kb, offset + 8); + if (keyCount > 2) + DES.adjustParity(kb, offset + 16); } /** - * Tests if a byte array has already been parity adjusted. + * Convenience method which calls the method with same name and three + * arguments, passing <code>3</code> as the value of the first parameter. * * @param kb The key bytes to test. * @param offset The starting offset into the key bytes. @@ -117,9 +143,37 @@ public class TripleDES */ public static boolean isParityAdjusted(byte[] kb, int offset) { - return DES.isParityAdjusted(kb, offset) - && DES.isParityAdjusted(kb, offset + 8) - && DES.isParityAdjusted(kb, offset + 16); + return isParityAdjusted(3, kb, offset); + } + + /** + * Tests if enough bytes, expected to be used as DES keys for a 3-DES 1-, 2- + * or 3-key cipher, located in a designated byte array, has already been + * parity adjusted. + * + * @param keyCount the number of independent DES keys. Can be either + * <code>1</code>, <code>2</code> or <code>3</code>. Any other value + * will cause an {@link IllegalArgumentException} to be raised. + * @param kb the array containing the key bytes to test. MUST have at least + * <code>8 * keyCount</code> bytes starting at offset position + * <code>offset</code>, otherwise an + * {@link ArrayIndexOutOfBoundsException} will be raised. + * @param offset the starting offset into the array. + * @return <code>true</code> if the bytes in <i>kb</i> starting at + * <i>offset</i> are parity adjusted. + * @see DES#isParityAdjusted(byte[],int) + * @see #adjustParity(int,byte[],int) + */ + public static boolean isParityAdjusted(int keyCount, byte[] kb, int offset) + { + if (keyCount < 1 || keyCount > 3) + throw new IllegalArgumentException("Invalid keyCount value: " + keyCount); + boolean result = DES.isParityAdjusted(kb, offset); + if (keyCount > 1) + result = result && DES.isParityAdjusted(kb, offset + 8); + if (keyCount > 2) + result = result && DES.isParityAdjusted(kb, offset + 16); + return result; } public Object clone() @@ -134,25 +188,49 @@ public class TripleDES public Iterator keySizes() { - return Collections.singleton(Integer.valueOf(KEY_SIZE)).iterator(); + ArrayList al = new ArrayList(); + al.add(Integer.valueOf(8)); + al.add(Integer.valueOf(16)); + al.add(Integer.valueOf(24)); + return Collections.unmodifiableList(al).iterator(); } public Object makeKey(byte[] kb, int bs) throws InvalidKeyException { - if (kb.length != KEY_SIZE) - throw new InvalidKeyException("TripleDES key must be 24 bytes"); - if (! isParityAdjusted(kb, 0)) - adjustParity(kb, 0); + if (kb.length != 8 && kb.length != 16 && kb.length != 24) + throw new InvalidKeyException("TripleDES key must be 8, 16 or 24 bytes: " + + kb.length); + Context ctx = new Context(); byte[] k1 = new byte[DES.KEY_SIZE]; - byte[] k2 = new byte[DES.KEY_SIZE]; - byte[] k3 = new byte[DES.KEY_SIZE]; System.arraycopy(kb, 0, k1, 0, DES.KEY_SIZE); - System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE); - System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE); - Context ctx = new Context(); + if (! DES.isParityAdjusted(k1, 0)) + DES.adjustParity(k1, 0); ctx.k1 = (DES.Context) des.makeKey(k1, bs); - ctx.k2 = (DES.Context) des.makeKey(k2, bs); - ctx.k3 = (DES.Context) des.makeKey(k3, bs); + + if (kb.length == 8) + { + ctx.k2 = (DES.Context) des.makeKey(k1, bs); + ctx.k3 = (DES.Context) des.makeKey(k1, bs); + } + else + { + byte[] k2 = new byte[DES.KEY_SIZE]; + System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE); + if (! DES.isParityAdjusted(k2, 0)) + DES.adjustParity(k2, 0); + ctx.k2 = (DES.Context) des.makeKey(k2, bs); + + byte[] k3 = new byte[DES.KEY_SIZE]; + if (kb.length == 16) + ctx.k3 = (DES.Context) des.makeKey(k1, bs); + else + { + System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE); + if (! DES.isParityAdjusted(k3, 0)) + DES.adjustParity(k3, 0); + ctx.k3 = (DES.Context) des.makeKey(k3, bs); + } + } return ctx; } diff --git a/gnu/javax/imageio/IIOInputStream.java b/gnu/javax/imageio/IIOInputStream.java new file mode 100644 index 000000000..2638e2fe2 --- /dev/null +++ b/gnu/javax/imageio/IIOInputStream.java @@ -0,0 +1,102 @@ +/* GIFStream.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio; + +import java.io.InputStream; +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; + +/** + * Implements InputStream on an ImageInputStream + * The purpose of this is to avoid IIO dependencies in the various decoders. + * (which only use read() anyway). + */ +public class IIOInputStream extends InputStream +{ + private ImageInputStream is; + + public IIOInputStream( ImageInputStream is ) + { + this.is = is; + } + + public int available() + { + return 0; + } + + public void close() throws IOException + { + is.close(); + } + + public void mark(int readlimit) + { + is.mark(); + } + + public boolean markSupported() + { + return true; + } + + public int read() throws IOException + { + return is.read(); + } + + public int read(byte[] b) throws IOException + { + return is.read(b); + } + + public int read(byte[] b, int offset, int length) throws IOException + { + return is.read(b, offset, length); + } + + public void reset() throws IOException + { + is.reset(); + } + + public long skip(long n) throws IOException + { + return is.skipBytes(n); + } +} diff --git a/gnu/javax/imageio/gif/GIFImageReader.java b/gnu/javax/imageio/gif/GIFImageReader.java index 66484fd88..47108dd0c 100644 --- a/gnu/javax/imageio/gif/GIFImageReader.java +++ b/gnu/javax/imageio/gif/GIFImageReader.java @@ -37,6 +37,8 @@ exception statement from your version. */ package gnu.javax.imageio.gif; +import gnu.javax.imageio.IIOInputStream; + import java.io.IOException; import java.io.InputStream; import javax.imageio.*; @@ -74,7 +76,7 @@ public class GIFImageReader extends ImageReader if( input instanceof InputStream ) file = new GIFFile( (InputStream)input ); else - file = new GIFFile( new GIFStream((ImageInputStream)input) ); + file = new GIFFile( new IIOInputStream((ImageInputStream)input) ); } catch(GIFFile.GIFException ge) { diff --git a/gnu/javax/imageio/gif/GIFImageReaderSpi.java b/gnu/javax/imageio/gif/GIFImageReaderSpi.java index a7b3ceb03..a31848623 100644 --- a/gnu/javax/imageio/gif/GIFImageReaderSpi.java +++ b/gnu/javax/imageio/gif/GIFImageReaderSpi.java @@ -37,6 +37,8 @@ exception statement from your version. */ package gnu.javax.imageio.gif; +import gnu.javax.imageio.IIOInputStream; + import java.io.InputStream; import java.io.IOException; import java.util.Locale; @@ -104,7 +106,7 @@ public class GIFImageReaderSpi extends ImageReaderSpi boolean retval; InputStream in; if( input instanceof ImageInputStream ) - in = new GIFStream( (ImageInputStream)input ); + in = new IIOInputStream( (ImageInputStream)input ); else in = (InputStream)input; diff --git a/gnu/javax/imageio/png/PNGChunk.java b/gnu/javax/imageio/png/PNGChunk.java new file mode 100644 index 000000000..6b53810c8 --- /dev/null +++ b/gnu/javax/imageio/png/PNGChunk.java @@ -0,0 +1,284 @@ +/* PNGChunk.java -- Generic PNG chunk + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +/** + * Class to load and validate a generic PNG chunk. + */ +public class PNGChunk +{ + + /** + * CRC table and initialization code. + */ + private static long[] crcTable; + + static + { + long c; + crcTable = new long[256]; + + for(int i = 0; i < 256; i++) + { + c = i; + for(int j = 0; j < 8; j++) + if( (c & 1) == 1 ) + c = 0xEDB88320L ^ (c >> 1); + else + c = c >> 1; + crcTable[i] = c; + } + } + + /** + * (recognized) PNG chunk types. + */ + public static final int TYPE_HEADER = 0x49484452; // 'IHDR' + public static final int TYPE_PALETTE = 0x504c5445;// 'PLTE' + public static final int TYPE_DATA = 0x49444154; // 'IDAT' + public static final int TYPE_TIME = 0x74494d45; // 'tIME' + public static final int TYPE_END = 0x49454e44; // 'IEND' + public static final int TYPE_PHYS = 0x70485973; // 'pHYS' + public static final int TYPE_GAMMA = 0x67414d41; // 'gAMA' + public static final int TYPE_PROFILE = 0x69434350; // 'iCCP' + + /** + * The chunk type - Represented in the file as 4 ASCII bytes, + */ + private int type; + + /** + * The chunk data + */ + protected byte[] data; + + /** + * The chunk's crc + */ + private int crc; + + /** + * Constructor for reading a generic chunk. + */ + protected PNGChunk( int type, byte[] data, int crc ) + { + this.type = type; + this.data = data; + this.crc = crc; + } + + /** + * Constructor for creating new chunks. + * (only used by subclasses - creating a generic chunk is rather useless) + */ + protected PNGChunk( int type ) + { + this.type = type; + } + + /** + * Loads a chunk from an InputStream. Does not perform validation, + * but will throw an IOException if the read fails. + * @param in - th einputstream to read from + * @param strict - if true, a PNGException is thrown on all invalid chunks, + * if false, only critical chunks will throw PNGExceptions. + */ + public static PNGChunk readChunk(InputStream in, boolean strict) + throws IOException, PNGException + { + byte data[] = new byte[4]; + if( in.read( data ) != 4 ) + throw new IOException("Could not read chunk length."); + int length = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + + if( in.read( data ) != 4 ) + throw new IOException("Could not read chunk type."); + int type = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + + byte[] chkdata = new byte[ length ]; + if( in.read( chkdata ) != length ) + throw new IOException("Could not read chunk data."); + + if( in.read( data ) != 4 ) + throw new IOException("Could not read chunk CRC."); + + int crc = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + + if( strict ) + return getChunk( type, chkdata, crc ); + else + { + try + { + return getChunk( type, chkdata, crc ); + } + catch(PNGException pnge) + { + if( isEssentialChunk( type ) ) + throw pnge; + return null; + } + } + } + + /** + * Returns a specialied object for a chunk, if we have one. + */ + private static PNGChunk getChunk( int type, byte[] data, int crc ) + throws PNGException + { + switch( type ) + { + case TYPE_HEADER: + return new PNGHeader( type, data, crc ); + case TYPE_DATA: + return new PNGData( type, data, crc ); + case TYPE_PALETTE: + return new PNGPalette( type, data, crc ); + case TYPE_TIME: + return new PNGTime( type, data, crc ); + case TYPE_PHYS: + return new PNGPhys( type, data, crc ); + case TYPE_GAMMA: + return new PNGGamma( type, data, crc ); + case TYPE_PROFILE: + return new PNGICCProfile( type, data, crc ); + default: + return new PNGChunk( type, data, crc ); + } + } + + /** + * Returns whether the chunk is essential or not + */ + private static boolean isEssentialChunk( int type ) + { + switch( type ) + { + case TYPE_HEADER: + case TYPE_DATA: + case TYPE_PALETTE: + case TYPE_END: + return true; + default: + return false; + } + } + + /** + * Validates the chunk + */ + public boolean isValidChunk() + { + return (crc == calcCRC()); + } + + /** + * Returns the chunk type. + */ + public int getType() + { + return type; + } + + /** + * Writes a PNG chunk to an output stream, + * performing the CRC calculation as well. + */ + public void writeChunk(OutputStream out) throws IOException + { + out.write( getInt(data.length) ); + out.write( getInt(type) ); + out.write( data ); + out.write( getInt(calcCRC()) ); + } + + /** + * Return whether the chunk contains any data. + */ + public boolean isEmpty() + { + return ( data.length == 0 ); + } + + /** + * Convenience method. Cast an int to four bytes (big endian). + * (Now why doesn't java have a simple way of doing this?) + */ + public static byte[] getInt(int intValue) + { + long i = (intValue & 0xFFFFFFFFL); + byte[] b = new byte[4]; + b[0] = (byte)((i & 0xFF000000L) >> 24); + b[1] = (byte)((i & 0x00FF0000L) >> 16); + b[2] = (byte)((i & 0x0000FF00L) >> 8); + b[3] = (byte)(i & 0x000000FFL); + return b; + } + + /** + * Calculates this chunk's CRC value. + */ + private int calcCRC() + { + long c = 0xFFFFFFFFL; + byte[] t = getInt( type ); + for(int i = 0; i < 4; i++) + c = crcTable[ (int)((c ^ t[i]) & 0xFF) ] ^ (c >> 8); + + for(int i = 0; i < data.length; i++) + c = crcTable[ (int)((c ^ data[i]) & 0xFF) ] ^ (c >> 8); + + return (int)(c ^ 0xFFFFFFFFL); + } + + public String toString() + { + return "PNG Chunk. Type: " + new String( getInt(type) ) + " , CRC: " + + crc + " , calculated CRC: "+calcCRC(); + } + +} diff --git a/gnu/javax/imageio/png/PNGData.java b/gnu/javax/imageio/png/PNGData.java new file mode 100644 index 000000000..2a8f8aa2d --- /dev/null +++ b/gnu/javax/imageio/png/PNGData.java @@ -0,0 +1,104 @@ +/* PNGData.java -- PNG IDAT chunk. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.zip.Inflater; +import java.util.zip.Deflater; + +/** + * A PNG IDAT (data) chunk. + */ +public class PNGData extends PNGChunk +{ + private int offset; + + protected PNGData( int type, byte[] data, int crc ) + { + super( type, data, crc ); + } + + protected PNGData( int chunkSize ) + { + super( PNGChunk.TYPE_DATA ); + data = new byte[ chunkSize ]; + offset = 0; + } + + /** + * Deflates the available data in def to the chunk. + * + * @return true if the chunk is filled and no more data can be written, + * false otherwise. + */ + public void deflateToChunk( Deflater def ) + { + offset += def.deflate( data, offset, data.length - offset ); + } + + /** + * Returns true if the chunk is filled. + */ + public boolean chunkFull() + { + return (offset >= data.length); + } + + /** + * Shrink the chunk to offset size, used for the last chunk in a stream + * (no trailing data!) + */ + public void shrink() + { + byte[] newData = new byte[ offset ]; + System.arraycopy( data, 0, newData, 0, offset ); + data = newData; + } + + /** + * Feeds the data in the chunk to a ZIP inflater object. + */ + public void feedToInflater( Inflater inf ) + { + inf.setInput( data ); + } + + public String toString() + { + return "PNG Data chunk. Length = "+data.length; + } +} diff --git a/gnu/javax/imageio/png/PNGDecoder.java b/gnu/javax/imageio/png/PNGDecoder.java new file mode 100644 index 000000000..20fc32ce3 --- /dev/null +++ b/gnu/javax/imageio/png/PNGDecoder.java @@ -0,0 +1,331 @@ +/* PNGDecoder.java + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.zip.Inflater; +import java.util.zip.DataFormatException; +import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.ComponentSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferUShort; +import java.awt.image.IndexColorModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.WritableRaster; +import java.awt.color.ColorSpace; + +public class PNGDecoder +{ + private PNGHeader header; + private byte[] raster; + private byte[] scanline, lastScanline; + private byte[] filterType; + private int offset, length; + private int currentScanline; + private final int stride; + private Inflater inflater; + private boolean readFilter; + private int bpp; // bytes per pixel + + /** + * Constructs a filter object for + */ + public PNGDecoder(PNGHeader header) + { + this.header = header; + offset = 0; + inflater = new Inflater(); + stride = header.getScanlineStride(); + length = stride * header.getHeight(); + + // Allocate the output raster + raster = new byte[ length ]; + scanline = new byte[ stride ]; + lastScanline = new byte[ stride ]; + currentScanline = 0; + readFilter = true; + bpp = header.bytesPerPixel(); + filterType = new byte[1]; + inflater = new Inflater(); + } + + private int getBytes( byte[] buf, int offset ) throws PNGException + { + try + { + return inflater.inflate( buf, offset, buf.length - offset); + } + catch(DataFormatException dfe) + { + throw new PNGException("Error inflating data."); + } + } + + /** + * Decodes a data chunk. + */ + public void addData( PNGData chunk ) throws PNGException + { + int n = 0; + if( isFinished() ) + return; + chunk.feedToInflater( inflater ); + do + { + if( readFilter ) + if( getBytes( filterType, 0 ) < 1 ) + return; + + n = getBytes( scanline, offset ); + + if( offset + n < stride ) + { + offset += n; + readFilter = false; + } + else + { + scanline = PNGFilter.unFilterScanline( filterType[0], scanline, + lastScanline, bpp ); + System.arraycopy( scanline, 0, + raster, currentScanline * stride, stride ); + lastScanline = scanline; + scanline = new byte[scanline.length]; + currentScanline++; + readFilter = true; + offset = 0; + } + } + while( n > 0 && currentScanline < header.getHeight() ); + } + + /** + * Parse the appropriate color type and create an AWT raster for it. + * @param raster - the file header. + */ + public WritableRaster getRaster( PNGHeader header ) + { + SampleModel sm = null; + DataBuffer db = null; + int t; + int width = header.getWidth(); + int height = header.getHeight(); + int depth = header.getDepth(); + + switch( header.getColorType() ) + { + case PNGHeader.GRAYSCALE_WITH_ALPHA: + if( depth == 8 ) + { + t = DataBuffer.TYPE_BYTE; + db = getByteBuffer(); + } + else + { + t = DataBuffer.TYPE_USHORT; + db = getShortBuffer(); + } + sm = new ComponentSampleModel(t, width, height, 2, width * 2, + new int[]{0, 1}); + break; + + case PNGHeader.GRAYSCALE: + switch( depth ) + { + case 16: + sm = new ComponentSampleModel(DataBuffer.TYPE_USHORT, + width, height, 1, width, + new int[]{ 0 }); + db = getShortBuffer(); + break; + + case 8: + sm = new ComponentSampleModel(DataBuffer.TYPE_BYTE, + width, height, 1, width, + new int[]{ 0 }); + db = getByteBuffer(); + break; + + default: + sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, depth); + db = getByteBuffer(); + break; + } + break; + + case PNGHeader.RGB: + if( depth == 8 ) + { + t = DataBuffer.TYPE_BYTE; + db = getByteBuffer(); + } + else + { + t = DataBuffer.TYPE_USHORT; + db = getShortBuffer(); + } + sm = new ComponentSampleModel(t, width, height, 3, 3 * width, + new int[]{0, 1, 2}); + break; + + case PNGHeader.RGB_WITH_ALPHA: + if( depth == 8 ) + { + t = DataBuffer.TYPE_BYTE; + db = getByteBuffer(); + } + else + { + t = DataBuffer.TYPE_USHORT; + db = getShortBuffer(); + } + + sm = new ComponentSampleModel(t, width, height, 4, width * 4, + new int[]{0, 1, 2, 3}); + break; + + case PNGHeader.INDEXED: + if( depth == 8 ) + sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, + new int[] {0xFF}); + else + sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, depth); + db = getByteBuffer(); + break; + } + + return Raster.createWritableRaster(sm, db, null); + } + + /** + * Wrap the raster with a DataBufferUShort, + * conversion is big-endian (PNG native). + */ + private DataBuffer getShortBuffer() + { + short[] data = new short[(raster.length >> 1)]; + for( int i = 0; i < data.length; i++ ) + data[i] = (short)(((raster[i * 2] & 0xFF) << 8) | + (raster[i * 2 + 1] & 0xFF)); + return new DataBufferUShort( data, data.length ); + } + + /** + * Wrap the raster with a DataBufferByte + */ + private DataBuffer getByteBuffer() + { + return new DataBufferByte( raster, raster.length ); + } + + public ColorModel getColorModel( ColorSpace cs, + int colorType, int depth ) + { + int[] bits; + boolean hasAlpha = false; + int transferType; + + switch( colorType ) + { + case PNGHeader.GRAYSCALE_WITH_ALPHA: + if( cs == null ) + cs = ColorSpace.getInstance( ColorSpace.CS_GRAY ); + hasAlpha = true; + bits = new int[]{ depth, depth }; + break; + + case PNGHeader.RGB: + bits = new int[]{ depth, depth, depth }; + break; + + case PNGHeader.RGB_WITH_ALPHA: + hasAlpha = true; + bits = new int[]{ depth, depth, depth, depth }; + break; + + case PNGHeader.GRAYSCALE: + if( depth < 8 ) + return grayPalette( depth ); + + if( cs == null ) + cs = ColorSpace.getInstance( ColorSpace.CS_GRAY ); + bits = new int[]{ depth }; + break; + + default: + case PNGHeader.INDEXED: + return null; // Handled by the palette chunk. + } + + if( cs == null ) + cs = ColorSpace.getInstance( ColorSpace.CS_sRGB ); + + + return new ComponentColorModel(cs, bits, hasAlpha, false, + (hasAlpha ? + ComponentColorModel.TRANSLUCENT : + ComponentColorModel.OPAQUE), + ((depth == 16) ? DataBuffer.TYPE_USHORT : + DataBuffer.TYPE_BYTE)); + } + + private IndexColorModel grayPalette(int depth) + { + byte[] c = new byte[ (1 << depth) ]; + for(int i = 0; i < c.length; i++) + c[i] = (byte)(255.0 * (((double)i) / ((double)c.length - 1.0))); + return new IndexColorModel(8, c.length, c, c, c); + } + + public byte[] getRaster() + { + return raster; + } + + public boolean isFinished() + { + return currentScanline >= header.getHeight(); + } +} diff --git a/gnu/javax/imageio/png/PNGEncoder.java b/gnu/javax/imageio/png/PNGEncoder.java new file mode 100644 index 000000000..c0a30a7ba --- /dev/null +++ b/gnu/javax/imageio/png/PNGEncoder.java @@ -0,0 +1,235 @@ +/* PNGEncoder.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.Vector; +import java.util.zip.Deflater; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferUShort; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + +public class PNGEncoder +{ + /** + * The default data chunk size. 8 kb. + */ + private static final int defaultChunkSize = 8192; + + private PNGHeader header; + private PNGPalette palette; + private int stride, bpp; + private byte[] rawData; + private PNGICCProfile profile; + + public PNGEncoder( BufferedImage bi ) throws PNGException + { + ColorModel c = bi.getColorModel(); + int width = bi.getWidth(); + int height = bi.getHeight(); + int depth = 0; + int colorType; + boolean interlace = false; + + if( c instanceof IndexColorModel ) + { + colorType = PNGHeader.INDEXED; + int n = ((IndexColorModel)c).getMapSize(); + if( n <= 2 ) + depth = 1; + else if( n <= 4 ) + depth = 2; + else if( n <= 16 ) + depth = 4; + else if( n <= 256 ) + depth = 8; + else + throw new PNGException("Depth must be <= 8 bits for indexed color."); + palette = new PNGPalette( ((IndexColorModel)c) ); + } + else + { + ColorSpace cs = c.getColorSpace(); + ColorSpace grayCS = ColorSpace.getInstance( ColorSpace.CS_GRAY ); + if( cs == grayCS || bi.getType() == BufferedImage.TYPE_BYTE_GRAY + || bi.getType() == BufferedImage.TYPE_USHORT_GRAY ) + colorType = c.hasAlpha() ? PNGHeader.GRAYSCALE_WITH_ALPHA : + PNGHeader.GRAYSCALE; + else + colorType = c.hasAlpha() ? PNGHeader.RGB_WITH_ALPHA : PNGHeader.RGB; + // Figure out the depth + int[] bits = c.getComponentSize(); + depth = bits[0]; + for(int i = 1; i < bits.length; i++ ) + if( bits[i] > depth ) depth = bits[i]; + if( (cs != grayCS && !cs.isCS_sRGB()) && cs instanceof ICC_ColorSpace ) + profile = new PNGICCProfile( ((ICC_ColorSpace)cs).getProfile() ); + } + + header = new PNGHeader(width, height, depth, colorType, interlace); + + stride = header.getScanlineStride(); // scanline stride + bpp = header.bytesPerPixel(); // bytes per pixel + getRawData( bi ); + } + + /** + * Returns the generated header. + */ + public PNGHeader getHeader() + { + return header; + } + + /** + * Returns the generated palette. + */ + public PNGPalette getPalette() + { + return palette; + } + + /** + * Returns the associated ICC profile, if any. + */ + public PNGICCProfile getProfile() + { + return profile; + } + + /** + * Encodes the raster and returns a Vector of PNGData chunks. + */ + public Vector encodeImage() + { + Deflater deflater = new Deflater(); // The deflater + boolean useFilter = PNGFilter.useFilter( header ); + byte[] lastScanline = new byte[ stride ]; + + byte[] data = new byte[ rawData.length + header.getHeight() ]; + + byte filterByte = PNGFilter.FILTER_NONE; + for( int i = 0; i < header.getHeight(); i++) + { + byte[] scanline = new byte[ stride ]; + System.arraycopy(rawData, (i * stride), scanline, 0, stride); + if( useFilter && i > 0) + filterByte = PNGFilter.chooseFilter( scanline, lastScanline, bpp); + + byte[] filtered = PNGFilter.filterScanline( filterByte, scanline, + lastScanline, bpp ); + data[i * (stride + 1)] = filterByte; + System.arraycopy(filtered, 0, data, 1 + (i * (stride + 1)), stride); + + lastScanline = scanline; + } + + deflater.setInput( data ); + deflater.finish(); + + PNGData chunk; + Vector chunks = new Vector(); + do + { + chunk = new PNGData( defaultChunkSize ); + chunk.deflateToChunk( deflater ); + chunks.add( chunk ); + } + while( chunk.chunkFull() ); + chunk.shrink(); // Shrink the last chunk. + return chunks; + } + + /** + * Get the image's raw data. + * FIXME: This may need improving on. + */ + private void getRawData( BufferedImage bi ) throws PNGException + { + WritableRaster raster = bi.getRaster(); + rawData = new byte[ stride * header.getHeight() ]; + if( header.isIndexed() ) + { + DataBuffer db = raster.getDataBuffer(); + if( !( db instanceof DataBufferByte ) ) + throw new PNGException("Unexpected DataBuffer for an IndexColorModel."); + byte[] data = ((DataBufferByte)db).getData(); + for(int i = 0; i < header.getHeight(); i++ ) + System.arraycopy( data, i * stride, rawData, i * stride, stride ); + return; + } + + if( header.getDepth() == 16 ) + { + DataBuffer db = raster.getDataBuffer(); + if( !( db instanceof DataBufferUShort ) ) + throw new PNGException("Unexpected DataBuffer for 16-bit."); + short[] data = ((DataBufferUShort)db).getData(); + for(int i = 0; i < header.getHeight(); i++ ) + for(int j = 0; j < ( stride >> 1); j++) + { + rawData[ j * 2 + i * stride ] = (byte)((data[j + i * (stride >> 1 )] & 0xFF00) >> 8); + rawData[ j * 2 + i * stride + 1 ] = (byte)(data[j + i * (stride >> 1 )] & 0xFF); + } + return; + } + + int size = ( header.getColorType() == PNGHeader.RGB_WITH_ALPHA ) ? 4 : 3; + int width = header.getWidth(); + int height = header.getHeight(); + int[] pixels = bi.getRGB( 0, 0, width, height, null, 0, width ); + + for( int i = 0; i < width * height; i++ ) + { + rawData[ i * size ] = (byte)((pixels[i] & 0xFF0000) >> 16); + rawData[ i * size + 1 ] = (byte)((pixels[i] & 0xFF00) >> 8); + rawData[ i * size + 2 ] = (byte)(pixels[i] & 0xFF); + } + + if( size == 4 ) + for( int i = 0; i < width * height; i++ ) + rawData[ i * size + 3 ] = (byte)((pixels[i] & 0xFF000000) >> 24); + } +} diff --git a/gnu/javax/imageio/png/PNGException.java b/gnu/javax/imageio/png/PNGException.java new file mode 100644 index 000000000..67486e579 --- /dev/null +++ b/gnu/javax/imageio/png/PNGException.java @@ -0,0 +1,48 @@ +/* PNGException.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.io.IOException; + +public class PNGException extends IOException +{ + public PNGException(String msg) + { + super( msg ); + } +} diff --git a/gnu/javax/imageio/png/PNGFile.java b/gnu/javax/imageio/png/PNGFile.java new file mode 100644 index 000000000..cc0ca297f --- /dev/null +++ b/gnu/javax/imageio/png/PNGFile.java @@ -0,0 +1,258 @@ +/* PNGFile.java -- High-level representation of a PNG file. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Vector; +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; +import java.awt.image.ColorModel; +import java.awt.image.IndexColorModel; +import java.awt.color.ColorSpace; + +public class PNGFile +{ + /** + * The PNG file signature. + */ + private static final byte[] signature = new byte[] + { (byte)137, 80, 78, 71, 13, 10, 26, 10 }; + + /** + * The end chunk in raw form, no need for anything fancy here, it's just + * 0 bytes of length, the "IEND" tag and its CRC. + */ + private static final byte[] endChunk = new byte[] + { 0, 0, 0, 0, (byte)0x49, (byte)0x45, (byte)0x4E, (byte)0x44, + (byte)0xAE, (byte)0x42, (byte)0x60, (byte)0x82 }; + + /** + * The loaded data. + */ + private Vector chunks; + + /** + * The Header chunk + */ + private PNGHeader header; + + /** + * Whether this file has a palette chunk or not. + */ + private boolean hasPalette; + + /** + * Image width and height. + */ + private int width, height; + + /** + * The decoder, if any. + */ + private PNGDecoder decoder; + + /** + * The encoder, if any. (Either this or the above must exist). + */ + private PNGEncoder encoder; + + /** + * The source of this PNG (if encoding) + */ + private BufferedImage sourceImage; + + /** + * Creates a PNGFile object from an InputStream. + */ + public PNGFile(InputStream in) throws IOException, PNGException + { + PNGChunk chunk; + byte[] fileHdr = new byte[8]; + chunks = new Vector(); + hasPalette = false; + + if( in.read( fileHdr ) != 8 ) + throw new IOException("Could not read file header."); + if( !validateHeader( fileHdr ) ) + throw new PNGException("Invalid file header. Not a PNG file."); + + chunk = PNGChunk.readChunk( in, false ); + if( !(chunk instanceof PNGHeader) ) + throw new PNGException("First chunk not a header chunk."); + header = (PNGHeader)chunk; + if( !header.isValidChunk() ) + throw new PNGException("First chunk not a valid header."); + System.out.println(header); + + decoder = new PNGDecoder( header ); + // Read chunks. + do + { + chunk = PNGChunk.readChunk( in, false ); + /* + * We could exit here or output some kind of warning. + * But in the meantime, we'll just silently drop invalid chunks. + */ + if( chunk.isValidChunk() ) + { + if( chunk instanceof PNGData ) + decoder.addData( (PNGData)chunk ); + else // Silently ignore multiple headers, and use only the first. + if( chunk.getType() != PNGChunk.TYPE_END ) + { + chunks.add( chunk ); + hasPalette |= ( chunk instanceof PNGPalette ); + } + } + else + System.out.println("WARNING: Invalid chunk!"); + } + while( chunk.getType() != PNGChunk.TYPE_END ); + + if( header.isIndexed() && !hasPalette ) + throw new PNGException("File is indexed color and has no palette."); + + width = header.getWidth(); + height = header.getHeight(); + } + + /** + * Creates a PNG file from an existing BufferedImage. + */ + public PNGFile(BufferedImage bi) throws PNGException + { + sourceImage = bi; + width = bi.getWidth(); + height = bi.getHeight(); + chunks = new Vector(); + encoder = new PNGEncoder( bi ); + header = encoder.getHeader(); + if( header.isIndexed() ) + chunks.add( encoder.getPalette() ); + + // Do the compression and put the data chunks in the list. + chunks.addAll( encoder.encodeImage() ); + } + + /** + * Writes a PNG file to an OutputStream + */ + public void writePNG(OutputStream out) throws IOException + { + out.write( signature ); // write the signature. + header.writeChunk( out ); + for( int i = 0; i < chunks.size(); i++ ) + { + PNGChunk chunk = ((PNGChunk)chunks.elementAt(i)); + chunk.writeChunk( out ); + } + out.write( endChunk ); + } + + /** + * Check 8 bytes to see if it's a valid PNG header. + */ + private boolean validateHeader( byte[] hdr ) + { + if( hdr.length != 8 ) + return false; + for( int i = 0; i < 8; i++ ) + if( signature[i] != hdr[i] ) + return false; + return true; + } + + /** + * Return a loaded image as a bufferedimage. + */ + public BufferedImage getBufferedImage() + { + if( decoder == null ) + return sourceImage; + + WritableRaster r = decoder.getRaster( header ); + ColorModel cm; + if( header.isIndexed() ) + { + PNGPalette pngp = getPalette(); + cm = pngp.getPalette( getColorSpace() ); + } + else + cm = decoder.getColorModel( getColorSpace(), + header.getColorType(), + header.getDepth() ); + + return new BufferedImage(cm, r, false, null); + } + + /** + * Find the palette chunk and return it + */ + private PNGPalette getPalette() + { + for(int i = 0; i < chunks.size(); i++ ) + if( chunks.elementAt(i) instanceof PNGPalette ) + return ((PNGPalette)chunks.elementAt(i)); + return null; + } + + /** + * Return the Color space to use, first preference is ICC profile, then + * a gamma chunk, or returns null for the default sRGB. + */ + private ColorSpace getColorSpace() + { + PNGICCProfile icc = null; + PNGGamma gamma = null; + for(int i = 0; i < chunks.size(); i++ ) + { + if( chunks.elementAt(i) instanceof PNGICCProfile ) + icc = ((PNGICCProfile)chunks.elementAt(i)); + else if(chunks.elementAt(i) instanceof PNGGamma ) + gamma = ((PNGGamma)chunks.elementAt(i)); + } + + if( icc != null ) + return icc.getColorSpace(); +// if( gamma != null && !header.isGrayscale()) +// return gamma.getColorSpace( header.isGrayscale() ); + return null; + } +} diff --git a/gnu/javax/imageio/png/PNGFilter.java b/gnu/javax/imageio/png/PNGFilter.java new file mode 100644 index 000000000..63af19929 --- /dev/null +++ b/gnu/javax/imageio/png/PNGFilter.java @@ -0,0 +1,237 @@ +/* PNGFilter.java -- PNG image filters. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +/** + * A utility class of static methods implementing the PNG filtering algorithms. + */ +public class PNGFilter +{ + + public static final byte FILTER_NONE = 0; + public static final byte FILTER_SUB = 1; + public static final byte FILTER_UP = 2; + public static final byte FILTER_AVERAGE = 3; + public static final byte FILTER_PAETH = 4; + + /** + * Return whether a filter should be used or FILTER_NONE, + * following the recommendations in the PNG spec. + */ + public static boolean useFilter( PNGHeader header ) + { + switch( header.getColorType() ) + { + case PNGHeader.INDEXED: + return false; + + case PNGHeader.GRAYSCALE: + case PNGHeader.RGB: + if( header.bytesPerPixel() <= 1 ) + return false; + case PNGHeader.GRAYSCALE_WITH_ALPHA: + case PNGHeader.RGB_WITH_ALPHA: + default: + return true; + } + } + + /** + * Heuristic for adaptively choosing a filter, following the scheme + * suggested in the PNG spec. + * @return a fiter type. + */ + public static byte chooseFilter( byte[] scanline, byte[] lastScanline, + int bpp) + + { + long[] values = new long[5]; + int idx = 0; + for( int i = 0; i < 5; i++ ) + { + byte[] filtered = filterScanline((byte)i, scanline, lastScanline, bpp); + values[i] = 0; + for(int j = 0; j < filtered.length; j++ ) + values[i] += (int)(filtered[j] & 0xFF); + if( values[ idx ] > values[i] ) + idx = i; + } + return (byte)idx; + } + + /** + * Filter a scanline. + */ + public static byte[] filterScanline( byte filtertype, byte[] scanline, + byte[] lastScanline, int bpp) + { + int stride = scanline.length; + byte[] out = new byte[ stride ]; + switch( filtertype ) + { + case FILTER_SUB: + for( int i = 0; i < bpp; i++) + out[ i ] = scanline[ i ]; + + for( int i = bpp; i < stride; i++ ) + out[i] = (byte)(scanline[ i ] - + scanline[ i - bpp ]); + break; + + case FILTER_UP: + for( int i = 0; i < stride; i++ ) + out[ i ] = (byte)(scanline[ i ] - lastScanline[ i ]); + break; + + case FILTER_AVERAGE: + for( int i = 0; i < bpp; i++) + out[ i ] = (byte)((scanline[ i ] & 0xFF) - ((lastScanline[ i ] & 0xFF) >> 1)); + for( int i = bpp; i < stride; i++ ) + out[ i ] = (byte)((scanline[ i ] & 0xFF) - + (((scanline[ i - bpp ] & 0xFF) + + (lastScanline[ i ] & 0xFF)) >> 1)); + break; + + case FILTER_PAETH: + for( int i = 0; i < stride; i++ ) + { + int x; + { + int a, b, c; + if( i >= bpp ) + { + a = (scanline[ i - bpp ] & 0xFF); // left + c = (lastScanline[ i - bpp ] & 0xFF); // upper-left + } + else + a = c = 0; + b = (lastScanline[ i ] & 0xFF); // up + + int p = (a + b - c); // initial estimate + // distances to a, b, c + int pa = (p > a) ? p - a : a - p; + int pb = (p > b) ? p - b : b - p; + int pc = (p > c) ? p - c : c - p; + // return nearest of a,b,c, + // breaking ties in order a,b,c. + if( pa <= pb && pa <= pc ) x = a; + else { if( pb <= pc ) x = b; + else x = c; + } + } + out[ i ] = (byte)(scanline[ i ] - x); + } + break; + default: + case FILTER_NONE: + return scanline; + } + return out; + } + + /** + * Unfilter a scanline. + */ + public static byte[] unFilterScanline( int filtertype, byte[] scanline, + byte[] lastScanline, int bpp) + { + int stride = scanline.length; + byte[] out = new byte[ stride ]; + switch( filtertype ) + { + + case FILTER_NONE: + System.arraycopy( scanline, 0, out, 0, stride ); + break; + + case FILTER_SUB: + for( int i = 0; i < bpp; i++) + out[ i ] = scanline[ i ]; + + for( int i = bpp; i < stride; i++ ) + out[ i ] = (byte)(scanline[ i ] + + out[ i - bpp ]); + break; + + case FILTER_UP: + for( int i = 0; i < stride; i++ ) + out[ i ] = (byte)(scanline[ i ] + lastScanline[ i ]); + break; + + case FILTER_AVERAGE: + for( int i = 0; i < bpp; i++) + out[ i ] = (byte)((scanline[ i ] & 0xFF) + ((lastScanline[ i ] & 0xFF) >> 1)); + for( int i = bpp; i < stride; i++ ) + out[ i ] = (byte)((scanline[ i ] & 0xFF) + + (((out[ i - bpp ] & 0xFF) + (lastScanline[ i ] & 0xFF)) >> 1)); + break; + + case FILTER_PAETH: + for( int i = 0; i < stride; i++ ) + { + int x; + { + int a, b, c; + if( i >= bpp ) + { + a = (out[ i - bpp ] & 0xFF); // left + c = (lastScanline[ i - bpp ] & 0xFF); // upper-left + } + else + a = c = 0; + b = (lastScanline[ i ] & 0xFF); // up + + int p = (a + b - c); // initial estimate + // distances to a, b, c + int pa = (p > a) ? p - a : a - p; + int pb = (p > b) ? p - b : b - p; + int pc = (p > c) ? p - c : c - p; + // return nearest of a,b,c, + // breaking ties in order a,b,c. + if( pa <= pb && pa <= pc ) x = a; + else { if( pb <= pc ) x = b; + else x = c; + } + } + out[ i ] = (byte)(scanline[ i ] + x); + } + break; + } + return out; + } +}
\ No newline at end of file diff --git a/gnu/javax/imageio/png/PNGGamma.java b/gnu/javax/imageio/png/PNGGamma.java new file mode 100644 index 000000000..af777d9b4 --- /dev/null +++ b/gnu/javax/imageio/png/PNGGamma.java @@ -0,0 +1,89 @@ +/* PNGGamma.java -- GAMA chunk. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.awt.color.ICC_ProfileGray; +import java.awt.color.ICC_ProfileRGB; +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ColorSpace; + +/** + * A PNG gAMA (gamma) chunk. + */ +public class PNGGamma extends PNGChunk +{ + private double gamma; + + protected PNGGamma( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 4 ) + throw new PNGException("Unexpectedly short time chunk. ("+data.length+" bytes)"); + long g = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + gamma = (double)g; + gamma = 100000.0/gamma; + } + + public PNGGamma( double g ) + { + super( TYPE_GAMMA ); + data = new byte[ 4 ]; + gamma = g; + long tmp = (long)(100000.0/gamma); + data[0] = (byte)((tmp & 0xFF000000) >> 24); + data[1] = (byte)((tmp & 0xFF0000) >> 16); + data[2] = (byte)((tmp & 0xFF00) >> 8); + data[3] = (byte)(tmp & 0xFF); + } + + /** + * Returns a ColorSpace object corresponding to this gamma value. + */ + public ColorSpace getColorSpace(boolean grayscale) + { + // FIXME. + return null; + } + + public String toString() + { + return "PNG Gamma chunk, value: "+gamma; + } +} diff --git a/gnu/javax/imageio/png/PNGHeader.java b/gnu/javax/imageio/png/PNGHeader.java new file mode 100644 index 000000000..c9ef2dc37 --- /dev/null +++ b/gnu/javax/imageio/png/PNGHeader.java @@ -0,0 +1,257 @@ +/* PNGHeader.java -- PNG Header + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +/** + * A PNG Header chunk. + */ +public class PNGHeader extends PNGChunk +{ + private int width, height, depth; + private int colorType, compression, filter, interlace; + + /** + * The valid interlace types. + */ + public static final int INTERLACE_NONE = 0; + public static final int INTERLACE_ADAM7 = 1; + + /** + * The valid color types. + */ + public static final int GRAYSCALE = 0; + public static final int RGB = 2; + public static final int INDEXED = 3; + public static final int GRAYSCALE_WITH_ALPHA = 4; + public static final int RGB_WITH_ALPHA = 6; + + /** + * Parses a PNG Header chunk. + */ + protected PNGHeader( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 13 ) + throw new PNGException("Unexpectedly short header chunk. (" + data.length + + " bytes)"); + + width = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + height = ((data[4] & 0xFF) << 24) | ( (data[5] & 0xFF) << 16 ) | + ((data[6] & 0xFF) << 8) | (data[7] & 0xFF); + depth = (data[8] & 0xFF); + colorType = (data[9] & 0xFF); + compression = (data[10] & 0xFF); + filter = (data[11] & 0xFF); + interlace = (data[12] & 0xFF); + } + + /** + * Create a PNG header chunk. + * Warning: This trusts that the parameters are valid. + */ + public PNGHeader(int width, int height, int depth, + int colorType, boolean interlace) + { + super( TYPE_HEADER ); + data = new byte[ 13 ]; + + this.width = width; + this.height = height; + this.depth = depth; + compression = filter = 0; + this.colorType = colorType; + this.interlace = interlace ? 1 : 0; + + // Build the data chunk. + byte[] a = getInt( width ); + byte[] b = getInt( height ); + data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = a[3]; + data[4] = b[0]; data[5] = b[1]; data[6] = b[2]; data[7] = b[3]; + data[8] = (byte)depth; + data[9] = (byte)colorType; + data[10] = (byte)compression; + data[11] = (byte)filter; + data[12] = (byte)this.interlace; + } + + /** + * Validates the header fields + */ + public boolean isValidChunk() + { + if( !super.isValidChunk() ) + return false; + + // width and height must be nonzero + if( width == 0 || height == 0 ) + return false; + // colorType can be 0,2,3,4,6 + if( (colorType & 0xFFFFFFF8) != 0 || colorType == 5 || colorType == 1) + return false; + // Possible valid depths are 1,2,4,8,16 + if( !((depth == 1) || (depth == 2) || (depth == 4) || + (depth == 8) || (depth == 16)) ) + return false; + if( colorType == INDEXED && depth == 16 ) + return false; + if( ( colorType == RGB || colorType == GRAYSCALE_WITH_ALPHA || + colorType == RGB_WITH_ALPHA ) && + depth < 8 ) + return false; + // Only compression and filter methods zero are defined + if( compression != 0 || filter != 0 ) + return false; + // Interlace methods, 0 and 1 are valid values. + if( (interlace & 0xFFFFFFFE) != 0 ) + return false; + + return true; + } + + /** + * Returns <code>true</code> if this PNG is indexed-color + */ + public boolean isIndexed() + { + return (colorType == INDEXED); + } + + /** + * Returns <code>true</code> if this PNG is grayscale + */ + public boolean isGrayscale() + { + return ((colorType == GRAYSCALE) || (colorType == GRAYSCALE_WITH_ALPHA)); + } + + /** + * Returns the color type of the image. + */ + public int getColorType() + { + return colorType; + } + + /** + * Returns whether the image is interlaced or not. + */ + public boolean isInterlaced() + { + return (interlace != 0); + } + + /** + * Returns the number of bytes per pixel. + */ + public int bytesPerPixel() + { + switch( colorType ) + { + case GRAYSCALE_WITH_ALPHA: + return ((depth * 2) >> 3); + case RGB: + return ((depth * 3) >> 3); + case RGB_WITH_ALPHA: + return ((depth * 4) >> 3); + + default: + case GRAYSCALE: + case INDEXED: + int i = (depth >> 3); + if( i > 0 ) return i; + return 1; // if bytes per pixel < 1, return 1 anyway. + } + } + + /** + * Returns the stride of one scanline, in bytes. + */ + public int getScanlineStride() + { + long nBits = 0; // bits per scanline - scanlines are on byte offsets. + switch( colorType ) + { + case GRAYSCALE: + nBits = width * depth; + break; + case RGB: + nBits = width * depth * 3; + break; + case INDEXED: + nBits = depth * width; + break; + case GRAYSCALE_WITH_ALPHA: + nBits = depth * width * 2; + break; + case RGB_WITH_ALPHA: + nBits = depth * width * 4; + break; + } + // Round up number of bits to the nearest byte + if( (nBits & 0x07) != 0 ) + nBits += (8 - (nBits & 0x07)); + + return (int)(nBits >> 3); // return # of bytes. + } + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + + public int getDepth() + { + return depth; + } + + /** + * Debugging string. + */ + public String toString() + { + return "Header Chunk. Image width:"+width+" height:"+height+ + " depth:"+depth+" color type:"+colorType+" compression type:"+ + compression+" filter type:"+ filter+" interlace:"+interlace; + } +} diff --git a/gnu/javax/imageio/png/PNGICCProfile.java b/gnu/javax/imageio/png/PNGICCProfile.java new file mode 100644 index 000000000..d2696e1c6 --- /dev/null +++ b/gnu/javax/imageio/png/PNGICCProfile.java @@ -0,0 +1,114 @@ +/* PNGICCProfile.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ColorSpace; +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.util.zip.InflaterInputStream; +import java.util.zip.Deflater; + +/** + * A PNG iCCP (ICC Profile) chunk. + */ +public class PNGICCProfile extends PNGChunk +{ + private String name; + private ICC_Profile profile; + // A generic profile name to use "ICC Profile" + private static final byte[] genericName = new byte[] + { 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65 }; + + protected PNGICCProfile( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + int i = 0; + while( data[i++] != 0 ); + try + { + name = new String(data, 0, i, "8859_1"); + } + catch(UnsupportedEncodingException e) + { + name = ""; // shouldn't really happen. + } + if( data[i++] != 0 ) + throw new PNGException("Can't handle nonzero compression types with iCCP chunks."); + try + { + ByteArrayInputStream bos = new ByteArrayInputStream( data, i, + data.length - i ); + profile = ICC_Profile.getInstance( new InflaterInputStream( bos ) ); + } + catch(IOException ioe) + { + throw new PNGException("Couldn't read iCCP profile chunk."); + } + System.out.println("Got profile:"+profile); + } + + public PNGICCProfile( ICC_Profile profile ) + { + super( TYPE_PROFILE ); + this.profile = profile; + byte[] profData = profile.getData(); + byte[] outData = new byte[ profData.length * 2 ]; + Deflater deflater = new Deflater(); + deflater.setInput( profData ); + deflater.finish(); + int n = deflater.deflate( outData ); + data = new byte[ n + 11 + 2 ]; + System.arraycopy(genericName, 0, data, 0, 11 ); + data[11] = data[12] = 0; // null separator and compression type. + // Copy compressed data + System.arraycopy(outData, 0, data, 13, n ); + } + + public ColorSpace getColorSpace() + { + return new ICC_ColorSpace( profile ); + } + + public String toString() + { + return "PNG ICC Profile, name: "+name; + } +} diff --git a/gnu/javax/imageio/png/PNGImageReader.java b/gnu/javax/imageio/png/PNGImageReader.java new file mode 100644 index 000000000..64aa3fea5 --- /dev/null +++ b/gnu/javax/imageio/png/PNGImageReader.java @@ -0,0 +1,224 @@ +/* PNGImageReader.java -- The ImageIO ImageReader for PNG + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.imageio.png; + +import gnu.javax.imageio.IIOInputStream; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; + +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageInputStream; + +/** + * The ImageIO ImageReader for PNG images. + * + * @author Roman Kennke (kennke@aicas.com) + */ +public class PNGImageReader + extends ImageReader +{ + + /** + * The PNG file. + */ + private PNGFile pngFile; + + /** + * The decoded image. + */ + private BufferedImage image; + + /** + * The supported image types for PNG. + */ + private ArrayList imageTypes; + + /** + * Creates a new instance. + * + * @param spi the corresponding ImageReaderSpi + */ + public PNGImageReader(PNGImageReaderSpi spi) + { + super(spi); + } + + /** + * Returns the height of the image. + */ + public int getHeight(int imageIndex) + throws IOException + { + checkIndex(imageIndex); + readImage(); + return image.getHeight(); + } + + /** + * Returns the width of the image. + * + * @param imageIndex the index of the image + * + * @return the width of the image + */ + public int getWidth(int imageIndex) throws IOException + { + checkIndex(imageIndex); + readImage(); + return image.getWidth(); + } + + /** + * Returns the image types for the image. + * + * @see ImageReader#getImageTypes(int) + */ + public Iterator getImageTypes(int imageIndex) + throws IOException + { + checkIndex(imageIndex); + readImage(); + if (imageTypes == null) + { + imageTypes = new ArrayList(); + imageTypes.add(new ImageTypeSpecifier(image.getColorModel(), + image.getSampleModel())); + } + return imageTypes.iterator(); + } + + /** + * Returns the number of images in the stream. + * + * @return the number of images in the stream + * + * @see ImageReader#getNumImages(boolean) + */ + public int getNumImages(boolean allowSearch) + throws IOException + { + return 1; + } + + /** + * Reads the image. + * + * @param imageIndex the index of the image to read + * @param param additional parameters + */ + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException + { + checkIndex(imageIndex); + readImage(); + return image; + } + + /** + * Sets the input and checks the input parameter. + * + * @see ImageReader#setInput(Object, boolean, boolean) + */ + public void setInput(Object input, + boolean seekForwardOnly, + boolean ignoreMetadata) + { + super.setInput(input, seekForwardOnly, ignoreMetadata); + if (! (input instanceof InputStream || input instanceof ImageInputStream)) + throw new IllegalArgumentException("Input not an ImageInputStream"); + } + + public IIOMetadata getImageMetadata(int imageIndex) + throws IOException + { + // TODO: Not (yet) supported. + checkIndex(imageIndex); + return null; + } + + public IIOMetadata getStreamMetadata() + throws IOException + { + // TODO: Not (yet) supported. + return null; + } + + /** + * Checks the image indexa and throws and IndexOutOfBoundsException if + * appropriate. + * + * @param index the index to check + */ + private void checkIndex(int index) + { + if (index > 0) + throw new IndexOutOfBoundsException("Image index out of bounds"); + } + + /** + * Makes sure that the image is read. + * + * @throws IOException if something goes wrong + */ + private void readImage() + throws IOException + { + if (pngFile == null) + { + if (input instanceof InputStream) + pngFile = new PNGFile((InputStream) input); + else if (input instanceof ImageInputStream) + pngFile = new PNGFile(new IIOInputStream((ImageInputStream) input)); + else + assert false : "Must not happen"; + } + + if (pngFile != null && image == null) + { + image = pngFile.getBufferedImage(); + } + } +} diff --git a/gnu/javax/imageio/png/PNGImageReaderSpi.java b/gnu/javax/imageio/png/PNGImageReaderSpi.java new file mode 100644 index 000000000..0092ab558 --- /dev/null +++ b/gnu/javax/imageio/png/PNGImageReaderSpi.java @@ -0,0 +1,128 @@ +/* PNGImageReaderSpi.java -- The ImageReader service provider for PNG + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.imageio.png; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +import javax.imageio.ImageReader; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +/** + * The ImageIO ImageReader service provider for PNG images. + * + * @author Roman Kennke (kennke@aicas.com) + */ +public class PNGImageReaderSpi + extends ImageReaderSpi +{ + + /** + * The PNG file signature. + */ + private static final byte[] SIGNATURE = new byte[] + { (byte) 137, 80, 78, 71, 13, 10, 26, 10 }; + + private static final String VENDOR_NAME = "GNU"; + static final String VERSION = "1.0"; + static final String READER_CLASSNAME = + "gnu.javax.imageio.png.PNGImageReader"; + static final String[] NAMES = { "Portable Network Graphics" }; + static final String[] SUFFIXES = { ".png" , ".PNG" }; + static final String[] MIME_TYPES = { "image/png" }; + static final String[] WRITER_SPI_NAMES = + new String[] { "gnu.javax.imageio.png.PNGWriterSpi" }; + static final Class[] INPUT_TYPES = new Class[]{ InputStream.class, + ImageInputStream.class}; + public PNGImageReaderSpi() + { + super(VENDOR_NAME, VERSION, NAMES, SUFFIXES, MIME_TYPES, READER_CLASSNAME, + INPUT_TYPES, WRITER_SPI_NAMES, false, null, null, null, null, false, + null, null, null, null); + } + + /** + * Determines if the PNG ImageReader can decode the specified input. + * + * @param source the source to decode + */ + public boolean canDecodeInput(Object source) throws IOException + { + boolean canDecode = false; + if (source instanceof ImageInputStream) + { + ImageInputStream in = (ImageInputStream) source; + in.mark(); + canDecode = true; + for (int i = 0; i < SIGNATURE.length && canDecode; i++) + { + byte sig = (byte) in.read(); + if (sig != SIGNATURE[i]) { + canDecode = false; + } + } + in.reset(); + } + return canDecode; + } + + /** + * Returns a new PNGImageReader instance. + * + * @param extension the extension, ignored + */ + public ImageReader createReaderInstance(Object extension) + throws IOException + { + return new PNGImageReader(this); + } + + /** + * Returns a description. + * + * @param locale the locale + */ + public String getDescription(Locale locale) + { + return "Portable Network Graphics"; + } + +} diff --git a/gnu/javax/imageio/png/PNGPalette.java b/gnu/javax/imageio/png/PNGPalette.java new file mode 100644 index 000000000..478129df5 --- /dev/null +++ b/gnu/javax/imageio/png/PNGPalette.java @@ -0,0 +1,127 @@ +/* PNGPalette.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.awt.color.ColorSpace; +import java.awt.image.IndexColorModel; + +/** + * A PNG Palette chunk. + */ +public class PNGPalette extends PNGChunk +{ + private int[] red,green,blue; + + protected PNGPalette( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + double l = data.length; + l /= 3.0; + // Check if it's divisible by 3. (Yuck.) + if( l - Math.floor(l) != 0.0 ) + throw new PNGException("Invalid size of palette chunk."); + int nEntries = (int)l; + + red = new int[ nEntries ]; + green = new int[ nEntries ]; + blue = new int[ nEntries ]; + for( int i = 0; i < nEntries; i++ ) + { + red[i] = (data[ i * 3 ] & 0xFF); + green[i] = (data[ i * 3 + 1 ] & 0xFF); + blue[i] = (data[ i * 3 + 2] & 0xFF); + } + } + + public PNGPalette( IndexColorModel cm ) + { + super( TYPE_PALETTE ); + int n = cm.getMapSize(); + data = new byte[ n * 3 ]; + red = new int[ n ]; + green = new int[ n ]; + blue = new int[ n ]; + for(int i = 0; i < n; i++ ) + { + red[i] = data[i * 3] = (byte)cm.getRed(i); + green[i] = data[i * 3 + 1] = (byte)cm.getGreen(i); + blue[i] = data[i * 3 + 2] = (byte)cm.getBlue(i); + } + } + + public IndexColorModel getPalette( ColorSpace cs ) + { + int nc = red.length; + byte[] r = new byte[nc]; + byte[] g = new byte[nc]; + byte[] b = new byte[nc]; + + if( cs == null ) + { + for(int i = 0; i < nc; i ++ ) + { + r[i] = (byte)red[i]; + g[i] = (byte)green[i]; + b[i] = (byte)blue[i]; + } + } + else + { + for(int i = 0; i < nc; i ++ ) + { + float[] in = new float[3]; + in[0] = (((float)red[i]) / 255f); + in[1] = (((float)green[i]) / 255f); + in[2] = (((float)blue[i]) / 255f); + float[] out = cs.toRGB( in ); + r[i] = (byte)( Math.round(out[0] * 255.0) ); + g[i] = (byte)( Math.round(out[1] * 255.0) ); + b[i] = (byte)( Math.round(out[2] * 255.0) ); + } + } + return new IndexColorModel(8, nc, r, g, b); + } + + public String toString() + { + String s = "PNG Palette:\n"; + for( int i = 0; i < red.length; i++) + s = s + "Index " + i + ": ["+ red[i] +", "+green[i]+", "+blue[i]+"]\n"; + return s; + } +} diff --git a/gnu/javax/imageio/png/PNGPhys.java b/gnu/javax/imageio/png/PNGPhys.java new file mode 100644 index 000000000..0a82d6acb --- /dev/null +++ b/gnu/javax/imageio/png/PNGPhys.java @@ -0,0 +1,112 @@ +/* PNGPhys.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +/** + * A PNG "pHYS" chunk - pixel physical dimensions + */ +public class PNGPhys extends PNGChunk +{ + long x, y; + double ratio; + boolean usesRatio; + + protected PNGPhys( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 9 ) + throw new PNGException("Unexpected size of pHYS chunk."); + x = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + y = ((data[4] & 0xFF) << 24) | ( (data[5] & 0xFF) << 16 ) | + ((data[6] & 0xFF) << 8) | (data[7] & 0xFF); + if(data[8] == 0) + { + ratio = ((double)x)/((double)y); + usesRatio = true; + } + } + + public PNGPhys( double ratio ) + { + super( TYPE_PHYS ); + + this.ratio = ratio; + usesRatio = true; + + if( ratio < 1.0 ) + { + y = 0xFFFFFFFF; + x = (long)(0xFFFFFFFFL * ratio); + } + else + { + x = 0xFFFFFFFF; + y = (long)(0xFFFFFFFFL * ratio); + } + makeData(); + } + + public PNGPhys( int x, int y ) + { + super( TYPE_PHYS ); + usesRatio = false; + this.x = x; + this.y = y; + makeData(); + } + + private void makeData() + { + data = new byte[ 9 ]; + byte[] a = getInt( (int)x ); + byte[] b = getInt( (int)y ); + data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = a[3]; + data[4] = b[0]; data[5] = b[1]; data[6] = b[2]; data[7] = b[3]; + data[7] = (usesRatio) ? 0 : (byte)0xFF; + } + + public String toString() + { + String s = "PNG Physical pixel size chunk."; + if( usesRatio ) + return s + " Aspect ratio (x/y): " + ratio; + else + return s + " " + x + " by " + y + " pixels per meter. (x, y)."; + } +} diff --git a/gnu/javax/imageio/png/PNGTime.java b/gnu/javax/imageio/png/PNGTime.java new file mode 100644 index 000000000..9b5c0332a --- /dev/null +++ b/gnu/javax/imageio/png/PNGTime.java @@ -0,0 +1,83 @@ +/* PNGTime.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.Date; + +/** + * A PNG tIME chunk. + */ +public class PNGTime extends PNGChunk +{ + private Date date; + + protected PNGTime( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 7 ) + throw new PNGException("Unexpectedly short time chunk. ("+data.length+" bytes)"); + + // PNG value is absolute (2006, not 106 or 06), java is from 1900. + int year = ( (data[0] & 0xFF) << 8 ) | (data[1] & 0xFF); + int month = (data[2] & 0xFF); // java counts from 0. PNG from 1. + int day = (data[3] & 0xFF); + int hour = (data[4] & 0xFF); + int minute = (data[5] & 0xFF); + int second = (data[6] & 0xFF); + date = new Date( year - 1900, month - 1, day, hour, minute, second ); + } + + public PNGTime( Date d ) + { + super( TYPE_TIME ); + data = new byte[ 7 ]; + int tmp = d.getYear() + 1900; + data[0] = (byte)((tmp & 0xFF00) >> 8); + data[1] = (byte)(tmp & 0x00FF); + data[2] = (byte)(d.getMonth() + 1); + data[3] = (byte)(d.getDay()); + data[4] = (byte)(d.getHours()); + data[5] = (byte)(d.getMinutes()); + data[6] = (byte)(d.getSeconds()); + } + + public String toString() + { + return "PNG Time chunk: "+date; + } +} diff --git a/include/GtkDragSourceContextPeer.h b/include/GtkDragSourceContextPeer.h new file mode 100644 index 000000000..4a43d811a --- /dev/null +++ b/include/GtkDragSourceContextPeer.h @@ -0,0 +1,23 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __GtkDragSourceContextPeer__ +#define __GtkDragSourceContextPeer__ + +#include <jni.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeStartDrag (JNIEnv *env, jobject, jobject, jint, jint, jint, jstring); +JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_connectSignals (JNIEnv *env, jobject, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create (JNIEnv *env, jobject, jobject); +JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeSetCursor (JNIEnv *env, jobject, jint) ; + + +#ifdef __cplusplus +} +#endif + +#endif /* __GtkDragSourceContextPeer__ */ diff --git a/include/Makefile.am b/include/Makefile.am index 7d7d51238..c36ff0687 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -75,7 +75,8 @@ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkTextFieldPeer.h \ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkToolkit.h \ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkWindowPeer.h \ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkVolatileImage.h \ -$(top_srcdir)/include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h +$(top_srcdir)/include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h \ +$(top_srcdir)/include/GtkDragSourceContextPeer.h QTPEER_H_FILES = \ $(top_srcdir)/include/gnu_java_awt_peer_qt_QtCheckboxPeer.h \ diff --git a/include/jvmti.h b/include/jvmti.h index d93ecbec9..23419f920 100644 --- a/include/jvmti.h +++ b/include/jvmti.h @@ -55,6 +55,10 @@ typedef struct _Jv_rawMonitorID *jrawMonitorID; #endif /* !_CLASSPATH_VM_JVMTI_TYPES_DEFINED */ +/* JVMTI Version */ +#define JVMTI_VERSION_1_0 0x30010000 +#define JVMTI_VERSION (JVMTI_VERSION_1_0 + 38) /* Spec version is 1.0.38 */ + #ifdef __cplusplus extern "C" { diff --git a/java/awt/Component.java b/java/awt/Component.java index 879d57211..6167f8f14 100644 --- a/java/awt/Component.java +++ b/java/awt/Component.java @@ -3856,6 +3856,8 @@ public abstract class Component the peer. For efficiency, the peer can choose not to invalidate if it is happy with the current dimensions, etc. */ + if (dropTarget != null) + dropTarget.addNotify(peer); } } diff --git a/java/awt/Graphics2D.java b/java/awt/Graphics2D.java index a833038c3..e0a1b4756 100644 --- a/java/awt/Graphics2D.java +++ b/java/awt/Graphics2D.java @@ -53,23 +53,21 @@ import java.util.Map; /** * An abstract class defining a device independent two-dimensional vector * graphics API. Concrete subclasses implement this API for output of - * vector graphics to: (*) + * vector graphics to: * <p> * <ul> * <li>a {@link javax.swing.JComponent} - in the * {@link javax.swing.JComponent#paint(Graphics)} method, the incoming * {@link Graphics} should always be an instance of - * <code>Graphics2D</code> (*);</li> + * <code>Graphics2D</code>;</li> * <li>a {@link BufferedImage} - see - * {@link BufferedImage#createGraphics()} (*);</li> + * {@link BufferedImage#createGraphics()};</li> * <li>a {@link java.awt.print.PrinterJob} - in the * {@link Printable#print(Graphics, PageFormat, int)} method, the incoming - * {@link Graphics} should always be an instance of <code>Graphics2D</code> - * (*).</li> + * {@link Graphics} should always be an instance of + * <code>Graphics2D</code>.</li> * </ul> * <p> - * (*) Support for this API is not fully implemented in GNU Classpath yet. - * <p> * Third party libraries provide support for output to other formats via this * API, including encapsulated postscript (EPS), portable document format (PDF), * and scalable vector graphics (SVG). diff --git a/java/awt/GridLayout.java b/java/awt/GridLayout.java index 80d964142..a6836681d 100644 --- a/java/awt/GridLayout.java +++ b/java/awt/GridLayout.java @@ -254,14 +254,11 @@ public class GridLayout implements LayoutManager, Serializable this.cols = newCols; } - /** Set the horizontal gap + /** Set the horizontal gap. An Exception is not thrown if hgap < 0. * @param hgap The horizontal gap - * @exception IllegalArgumentException If the hgap value is less than zero. */ public void setHgap (int hgap) { - if (hgap < 0) - throw new IllegalArgumentException ("horizontal gap must be nonnegative"); this.hgap = hgap; } @@ -280,21 +277,18 @@ public class GridLayout implements LayoutManager, Serializable this.rows = newRows; } - /** Set the vertical gap. + /** Set the vertical gap. An Exception is not thrown if vgap < 0. * @param vgap The vertical gap - * @exception IllegalArgumentException If the vgap value is less than zero. */ public void setVgap (int vgap) { - if (vgap < 0) - throw new IllegalArgumentException ("vertical gap must be nonnegative"); this.vgap = vgap; } /** Return String description of this object. */ public String toString () { - return ("[" + getClass ().getName () + return (getClass ().getName () + "[" + ",hgap=" + hgap + ",vgap=" + vgap + ",rows=" + rows + ",cols=" + cols + "]"); diff --git a/java/awt/LightweightDispatcher.java b/java/awt/LightweightDispatcher.java index e777145b0..05f88dcf6 100644 --- a/java/awt/LightweightDispatcher.java +++ b/java/awt/LightweightDispatcher.java @@ -152,8 +152,11 @@ class LightweightDispatcher target = findTarget(parent, loc); while (target == null && parent != null) { - if (parent.getMouseListeners().length > 0 - || parent.getMouseMotionListeners().length > 0) + if (parent.mouseListener != null + || parent.mouseMotionListener != null + || (parent.eventMask + & (AWTEvent.MOUSE_EVENT_MASK + | AWTEvent.MOUSE_MOTION_EVENT_MASK)) != 0) { target = parent; } @@ -297,8 +300,11 @@ class LightweightDispatcher if (child.isShowing()) { if (child.contains(loc.x - child.getX(), loc.y - child.getY()) - && (child.getMouseListeners().length > 0 - || child.getMouseMotionListeners().length > 0)) + && (child.mouseListener != null + || child.mouseMotionListener != null + || (child.eventMask + & (AWTEvent.MOUSE_EVENT_MASK + | AWTEvent.MOUSE_MOTION_EVENT_MASK)) != 0)) { target = child; break; diff --git a/java/awt/dnd/DragSource.java b/java/awt/dnd/DragSource.java index 90b62b5db..2ab748270 100644 --- a/java/awt/dnd/DragSource.java +++ b/java/awt/dnd/DragSource.java @@ -51,7 +51,6 @@ import java.awt.datatransfer.FlavorMap; import java.awt.datatransfer.SystemFlavorMap; import java.awt.datatransfer.Transferable; import java.awt.dnd.peer.DragSourceContextPeer; -import java.awt.event.MouseMotionListener; import java.io.Serializable; import java.util.EventListener; @@ -77,6 +76,8 @@ public class DragSource implements Serializable private transient DragSourceMotionListener dragSourceMotionListener; private static DragSource ds; + private DragSourceContextPeer peer; + private DragSourceContext context; /** * Initializes the drag source. @@ -140,12 +141,17 @@ public class DragSource implements Serializable // it to the peer, passing itself as a parameter. Now, the native system has // access to the Transferable through the context. + // FIXME: Add check to determine if dragging. + try { flavorMap = map; - DragSourceContextPeer peer = Toolkit.getDefaultToolkit(). - createDragSourceContextPeer(trigger); - DragSourceContext context = createDragSourceContext(peer, trigger, + + if (peer == null) + peer = Toolkit.getDefaultToolkit().createDragSourceContextPeer(trigger); + + if (context == null) + context = createDragSourceContext(peer, trigger, dragCursor, dragImage, imageOffset, trans, @@ -307,4 +313,17 @@ public class DragSource implements Serializable // Return an empty EventListener array. return (T[]) new EventListener [0]; } + + /** + * TODO + * @return + * + * @since 1.5 + */ + public static int getDragThreshold() + throws NotImplementedException + { + // FIXME: Not implemented. + return 4; + } } // class DragSource diff --git a/java/awt/dnd/DropTarget.java b/java/awt/dnd/DropTarget.java index 2698b1dae..a3650567f 100644 --- a/java/awt/dnd/DropTarget.java +++ b/java/awt/dnd/DropTarget.java @@ -49,6 +49,7 @@ import java.awt.dnd.peer.DropTargetPeer; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.peer.ComponentPeer; +import java.awt.peer.LightweightPeer; import java.io.Serializable; import java.util.EventListener; import java.util.TooManyListenersException; @@ -160,12 +161,15 @@ public class DropTarget if (GraphicsEnvironment.isHeadless ()) throw new HeadlessException (); - component = c; - actions = i; + setComponent(c); + setDefaultActions(i); dropTargetListener = dtl; flavorMap = fm; setActive (b); + + if (c != null) + c.setDropTarget(this); } /** @@ -275,9 +279,16 @@ public class DropTarget public void addNotify(ComponentPeer p) { + Component c = component; + while (c != null && p instanceof LightweightPeer) + { + p = c.getPeer(); + c = c.getParent(); + } + if (p instanceof DropTargetPeer) { - peer = (DropTargetPeer) p; + peer = ((DropTargetPeer) p); peer.addDropTarget(this); } else diff --git a/java/awt/dnd/DropTargetDragEvent.java b/java/awt/dnd/DropTargetDragEvent.java index ea5b682d1..838141ec3 100644 --- a/java/awt/dnd/DropTargetDragEvent.java +++ b/java/awt/dnd/DropTargetDragEvent.java @@ -40,6 +40,7 @@ package java.awt.dnd; import java.awt.Point; import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; import java.util.List; /** @@ -136,4 +137,17 @@ public class DropTargetDragEvent extends DropTargetEvent { context.rejectDrag (); } + + /** + * TODO + * + * @return + * + * @since 1.5 + */ + public Transferable getTransferable() + { + // FIXME: Not implemented + return null; + } } // class DropTargetDragEvent diff --git a/java/awt/image/BandedSampleModel.java b/java/awt/image/BandedSampleModel.java index ed6abcf4f..a346cf6af 100644 --- a/java/awt/image/BandedSampleModel.java +++ b/java/awt/image/BandedSampleModel.java @@ -36,6 +36,8 @@ exception statement from your version. */ package java.awt.image; +import gnu.java.awt.Buffers; + /** * A sample model that reads each sample value from a separate band in the * {@link DataBuffer}. @@ -89,6 +91,17 @@ public final class BandedSampleModel extends ComponentSampleModel { super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets); } + + /** + * Creates a new data buffer that is compatible with this sample model. + * + * @return The new data buffer. + */ + public DataBuffer createDataBuffer() + { + int size = scanlineStride * height; + return Buffers.createBuffer(getDataType(), size, numBanks); + } /** * Creates a new <code>SampleModel</code> that is compatible with this diff --git a/java/awt/image/BufferedImageOp.java b/java/awt/image/BufferedImageOp.java index 2ecbec056..f6a24c976 100644 --- a/java/awt/image/BufferedImageOp.java +++ b/java/awt/image/BufferedImageOp.java @@ -1,5 +1,5 @@ /* BufferedImageOp.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -43,13 +43,65 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** - * NEEDS DOCUMENTATION + * An operation that is performed on one <code>BufferedImage</code> (the + * source) producing a new <code>BufferedImage</code> (the destination). */ public interface BufferedImageOp { + /** + * Performs an operation on the source image, returning the result in a + * <code>BufferedImage</code>. If <code>dest</code> is <code>null</code>, a + * new <code>BufferedImage</code> will be created by calling the + * {@link #createCompatibleDestImage} method. If <code>dest</code> + * is not <code>null</code>, the result is written to <code>dest</code> then + * returned (this avoids creating a new <code>BufferedImage</code> each + * time this method is called). + * + * @param src the source image. + * @param dst the destination image (<code>null</code> permitted). + * + * @return The filterd image. + */ BufferedImage filter(BufferedImage src, BufferedImage dst); + + /** + * Returns the bounds of the destination image on the basis of this + * <code>BufferedImageOp</code> being applied to the specified source image. + * + * @param src the source image. + * + * @return The destination bounds. + */ Rectangle2D getBounds2D(BufferedImage src); + + /** + * Returns a new <code>BufferedImage</code> that can be used by this + * <code>BufferedImageOp</code> as the destination image when filtering + * the specified source image. + * + * @param src the source image. + * @param dstCM the color model for the destination image. + * + * @return A new image that can be used as the destination image. + */ BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM); + + /** + * Returns the point on the destination image that corresponds to the given + * point on the source image. + * + * @param src the source point. + * @param dst the destination point (<code>null</code> permitted). + * + * @return The destination point. + */ Point2D getPoint2D(Point2D src, Point2D dst); + + /** + * Returns the rendering hints for this operation. + * + * @return The rendering hints. + */ RenderingHints getRenderingHints(); -} // interface BufferedImageOp + +} diff --git a/java/awt/image/ByteLookupTable.java b/java/awt/image/ByteLookupTable.java index df02d0a1b..ecc0023af 100644 --- a/java/awt/image/ByteLookupTable.java +++ b/java/awt/image/ByteLookupTable.java @@ -1,5 +1,5 @@ /* ByteLookupTable.java -- Java class for a pixel translation table. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -60,14 +60,20 @@ public class ByteLookupTable extends LookupTable * components. * * @param offset Offset to be subtracted. - * @param data Array of lookup tables. + * @param data Array of lookup tables (<code>null</code> not permitted). * @exception IllegalArgumentException if offset < 0 or data.length < 1. */ public ByteLookupTable(int offset, byte[][] data) throws IllegalArgumentException { super(offset, data.length); - this.data = data; + + // tests show that Sun's implementation creates a new array to store the + // references from the incoming 'data' array - not sure why, but we'll + // match that behaviour just in case it matters... + this.data = new byte[data.length][]; + for (int i = 0; i < data.length; i++) + this.data[i] = data[i]; } /** @@ -77,13 +83,16 @@ public class ByteLookupTable extends LookupTable * table. The same table is applied to all pixel components. * * @param offset Offset to be subtracted. - * @param data Lookup table for all components. + * @param data Lookup table for all components (<code>null</code> not + * permitted). * @exception IllegalArgumentException if offset < 0. */ public ByteLookupTable(int offset, byte[] data) throws IllegalArgumentException { super(offset, 1); + if (data == null) + throw new NullPointerException("Null 'data' argument."); this.data = new byte[][] {data}; } diff --git a/java/awt/image/ComponentSampleModel.java b/java/awt/image/ComponentSampleModel.java index b4e9450b0..bccabbbca 100644 --- a/java/awt/image/ComponentSampleModel.java +++ b/java/awt/image/ComponentSampleModel.java @@ -272,9 +272,7 @@ public class ComponentSampleModel extends SampleModel // 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]); - } + highestOffset = Math.max(highestOffset, bandOffsets[b]); int size = pixelStride * (width - 1) + scanlineStride * (height - 1) + highestOffset + 1; @@ -678,6 +676,9 @@ public class ComponentSampleModel extends SampleModel */ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) { + if (x < 0 || x >= width || y < 0 || y >= height) + throw new ArrayIndexOutOfBoundsException("Pixel (" + x + ", " + y + + ") is out of bounds."); int offset = pixelStride * x + scanlineStride * y; if (iArray == null) iArray = new int[numBands]; @@ -736,10 +737,16 @@ public class ComponentSampleModel extends SampleModel * * @return The sample value. * + * @throws ArrayIndexOutOfBoundsException if <code>(x, y)</code> is outside + * the bounds <code>[0, 0, width, height]</code>. + * * @see #setSample(int, int, int, int, DataBuffer) */ public int getSample(int x, int y, int b, DataBuffer data) { + if (x < 0 || x >= width || y < 0 || y >= height) + throw new ArrayIndexOutOfBoundsException("Sample (" + x + ", " + y + + ") is out of bounds."); return data.getElem(bankIndices[b], getOffset(x, y, b)); } diff --git a/java/awt/image/ConvolveOp.java b/java/awt/image/ConvolveOp.java index 1f73f75b2..ffb834874 100644 --- a/java/awt/image/ConvolveOp.java +++ b/java/awt/image/ConvolveOp.java @@ -1,5 +1,5 @@ /* ConvolveOp.java -- - Copyright (C) 2004, 2005 Free Software Foundation -- ConvolveOp + Copyright (C) 2004, 2005, 2006, Free Software Foundation -- ConvolveOp This file is part of GNU Classpath. @@ -42,7 +42,6 @@ import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; -import java.util.Arrays; /** * Convolution filter. @@ -190,112 +189,101 @@ public class ConvolveOp implements BufferedImageOp, RasterOp * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, * java.awt.image.WritableRaster) */ - public final WritableRaster filter(Raster src, WritableRaster dest) { + public final WritableRaster filter(Raster src, WritableRaster dest) + { if (src == dest) - throw new IllegalArgumentException(); - if (src.getWidth() < kernel.getWidth() || - src.getHeight() < kernel.getHeight()) - throw new ImagingOpException(null); - + throw new IllegalArgumentException("src == dest is not allowed."); + if (kernel.getWidth() > src.getWidth() + || kernel.getHeight() > src.getHeight()) + throw new ImagingOpException("The kernel is too large."); if (dest == null) dest = createCompatibleDestRaster(src); - else if (src.numBands != dest.numBands) - throw new ImagingOpException(null); + else if (src.getNumBands() != dest.getNumBands()) + throw new ImagingOpException("src and dest have different band counts."); - // Deal with bottom edge - if (edge == EDGE_ZERO_FILL) - { - float[] zeros = new float[src.getNumBands() * src.getWidth() - * (kernel.getYOrigin() - 1)]; - Arrays.fill(zeros, 0); - dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(), - kernel.getYOrigin() - 1, zeros); - } - else - { - float[] vals = new float[src.getNumBands() * src.getWidth() - * (kernel.getYOrigin() - 1)]; - src.getPixels(src.getMinX(), src.getMinY(), src.getWidth(), - kernel.getYOrigin() - 1, vals); - dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(), - kernel.getYOrigin() - 1, vals); - } + // calculate the borders that the op can't reach... + int kWidth = kernel.getWidth(); + int kHeight = kernel.getHeight(); + int left = kernel.getXOrigin(); + int right = Math.max(kWidth - left - 1, 0); + int top = kernel.getYOrigin(); + int bottom = Math.max(kHeight - top - 1, 0); - // Handle main section + // process the region that is reachable... + int regionW = src.width - left - right; + int regionH = src.height - top - bottom; float[] kvals = kernel.getKernelData(null); + float[] tmp = new float[kWidth * kHeight]; - float[] tmp = new float[kernel.getWidth() * kernel.getHeight()]; - for (int y = src.getMinY() + kernel.getYOrigin(); - y < src.getMinY() + src.getHeight() - kernel.getYOrigin() / 2; y++) - { - // Handle unfiltered edge pixels at start of line - float[] t1 = new float[(kernel.getXOrigin() - 1) * src.getNumBands()]; - if (edge == EDGE_ZERO_FILL) - Arrays.fill(t1, 0); - else - src.getPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1); - dest.setPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1); - - for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++) + for (int x = 0; x < regionW; x++) { - // FIXME: This needs a much more efficient implementation - for (int b = 0; b < src.getNumBands(); b++) - { - float v = 0; - src.getSamples(x, y, kernel.getWidth(), kernel.getHeight(), b, tmp); - for (int i=0; i < tmp.length; i++) - v += tmp[i] * kvals[i]; - dest.setSample(x, y, b, v); - } + for (int y = 0; y < regionH; y++) + { + // FIXME: This needs a much more efficient implementation + for (int b = 0; b < src.getNumBands(); b++) + { + float v = 0; + src.getSamples(x, y, kWidth, kHeight, b, tmp); + for (int i = 0; i < tmp.length; i++) + v += tmp[tmp.length - i - 1] * kvals[i]; + // FIXME: in the above line, I've had to reverse the order of + // the samples array to make the tests pass. I haven't worked + // out why this is necessary. + dest.setSample(x + kernel.getXOrigin(), y + kernel.getYOrigin(), + b, v); + } + } } - - // Handle unfiltered edge pixels at end of line - float[] t2 = new float[(kernel.getWidth() / 2) * src.getNumBands()]; - if (edge == EDGE_ZERO_FILL) - Arrays.fill(t2, 0); - else - src.getPixels(src.getMinX() + src.getWidth() - - (kernel.getWidth() / 2), - y, kernel.getWidth() / 2, 1, t2); - dest.setPixels(src.getMinX() + src.getWidth() - (kernel.getWidth() / 2), - y, kernel.getWidth() / 2, 1, t2); - } - for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) - for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++) + + // fill in the top border + fillEdge(src, dest, 0, 0, src.width, top, edge); + + // fill in the bottom border + fillEdge(src, dest, 0, src.height - bottom, src.width, bottom, edge); + + // fill in the left border + fillEdge(src, dest, 0, top, left, regionH, edge); + + // fill in the right border + fillEdge(src, dest, src.width - right, top, right, regionH, edge); + + return dest; + } + + /** + * Fills a range of pixels (typically at the edge of a raster) with either + * zero values (if <code>edgeOp</code> is <code>EDGE_ZERO_FILL</code>) or the + * corresponding pixel values from the source raster (if <code>edgeOp</code> + * is <code>EDGE_NO_OP</code>). This utility method is called by the + * {@link #fillEdge(Raster, WritableRaster, int, int, int, int, int)} method. + * + * @param src the source raster. + * @param dest the destination raster. + * @param x the x-coordinate of the top left pixel in the range. + * @param y the y-coordinate of the top left pixel in the range. + * @param w the width of the pixel range. + * @param h the height of the pixel range. + * @param edgeOp indicates how to determine the values for the range + * (either {@link #EDGE_ZERO_FILL} or {@link #EDGE_NO_OP}). + */ + private void fillEdge(Raster src, WritableRaster dest, int x, int y, int w, + int h, int edgeOp) + { + if (w <= 0) + return; + if (h <= 0) + return; + if (edgeOp == EDGE_ZERO_FILL) // fill region with zeroes { - + float[] zeros = new float[src.getNumBands() * w * h]; + dest.setPixels(x, y, w, h, zeros); } - for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++) - for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++) + else // copy pixels from source { - + float[] pixels = new float[src.getNumBands() * w * h]; + src.getPixels(x, y, w, h, pixels); + dest.setPixels(x, y, w, h, pixels); } - - // Handle top edge - if (edge == EDGE_ZERO_FILL) - { - float[] zeros = new float[src.getNumBands() * src.getWidth() * - (kernel.getHeight() / 2)]; - Arrays.fill(zeros, 0); - dest.setPixels(src.getMinX(), - src.getHeight() + src.getMinY() - (kernel.getHeight() / 2), - src.getWidth(), kernel.getHeight() / 2, zeros); - } - else - { - float[] vals = new float[src.getNumBands() * src.getWidth() * - (kernel.getHeight() / 2)]; - src.getPixels(src.getMinX(), - src.getHeight() + src.getMinY() - - (kernel.getHeight() / 2), - src.getWidth(), kernel.getHeight() / 2, vals); - dest.setPixels(src.getMinX(), - src.getHeight() + src.getMinY() - - (kernel.getHeight() / 2), - src.getWidth(), kernel.getHeight() / 2, vals); - } - - return dest; } /* (non-Javadoc) diff --git a/java/awt/image/Kernel.java b/java/awt/image/Kernel.java index f7c29c3cd..8361c0cf9 100644 --- a/java/awt/image/Kernel.java +++ b/java/awt/image/Kernel.java @@ -1,5 +1,5 @@ /* Kernel.java -- Java class for an image processing kernel - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,21 +44,32 @@ package java.awt.image; * values representing a 2-dimensional array in row-major order. * * @author Jerry Quinn (jlquinn@optonline.net) - * @version 1.0 */ public class Kernel implements Cloneable { + /** The kernel width. */ private final int width; + + /** The kernel height. */ private final int height; + + /** Internal storage for the kernel's values. */ private final float[] data; /** - * Creates a new <code>Kernel</code> instance. + * Creates a new <code>Kernel</code> instance with the specified dimensions + * and values. The first <code>width * height</code> values in the specified + * <code>data</code> array are copied to internal storage. * - * @param width The 2D width of data. - * @param height The 2D height of data. - * @param data The source data array. - * @exception IllegalArgumentException if width * height < data.length. + * @param width the kernel width. + * @param height the kernel height. + * @param data the source data array (<code>null</code> not permitted). + * + * @throws IllegalArgumentException if <code>data.length</code> is less than + * <code>width * height</code>. + * @throws IllegalArgumentException if <code>width</code> or + * <code>height</code> is less than zero. + * @throws NullPointerException if <code>data</code> is <code>null</code>. */ public Kernel(int width, int height, float[] data) throws IllegalArgumentException @@ -72,7 +83,10 @@ public class Kernel implements Cloneable } /** - * Return the X origin: (width - 1) / 2 + * Returns the x-origin for the kernel, which is calculated as + * <code>(width - 1) / 2</code>. + * + * @return The x-origin for the kernel. */ public final int getXOrigin() { @@ -80,7 +94,10 @@ public class Kernel implements Cloneable } /** - * Return the Y origin: (height - 1) / 2 + * Returns the y-origin for the kernel, which is calculated as + * <code>(height - 1) / 2</code>. + * + * @return The y-origin for the kernel. */ public final int getYOrigin() { @@ -88,6 +105,8 @@ public class Kernel implements Cloneable } /** + * Returns the kernel width (as supplied to the constructor). + * * @return The kernel width. */ public final int getWidth() @@ -96,6 +115,8 @@ public class Kernel implements Cloneable } /** + * Returns the kernel height (as supplied to the constructor). + * * @return The kernel height. */ public final int getHeight() @@ -104,20 +125,25 @@ public class Kernel implements Cloneable } /** - * Return the kernel data. + * Returns an array containing a copy of the kernel data. If the + * <code>data</code> argument is non-<code>null</code>, the kernel values + * are copied into it and then <code>data</code> is returned as the result. + * If the <code>data</code> argument is <code>null</code>, this method + * allocates a new array then populates and returns it. * - * If data is null, allocates a new array and returns it. Otherwise, the - * kernel values are copied into data. - * - * @param data Array to copy values into, or null. + * @param data an array to copy the return values into (if + * <code>null</code>, a new array is allocated). + * * @return The array with copied values. - * @exception IllegalArgumentException if data != null and too small. + * + * @throws IllegalArgumentException if <code>data.length</code> is less than + * the kernel's <code>width * height</code>. */ public final float[] getKernelData(float[] data) throws IllegalArgumentException { if (data == null) - return (float[])this.data.clone(); + return (float[]) this.data.clone(); if (data.length < this.data.length) throw new IllegalArgumentException(); @@ -127,13 +153,15 @@ public class Kernel implements Cloneable } /** + * Returns a clone of this kernel. + * * @return a clone of this Kernel. */ public Object clone() { try { - return super.clone(); + return super.clone(); } catch (CloneNotSupportedException e) { diff --git a/java/awt/image/MultiPixelPackedSampleModel.java b/java/awt/image/MultiPixelPackedSampleModel.java index ddd38208d..8732e5765 100644 --- a/java/awt/image/MultiPixelPackedSampleModel.java +++ b/java/awt/image/MultiPixelPackedSampleModel.java @@ -231,10 +231,12 @@ public class MultiPixelPackedSampleModel extends SampleModel * @param y the y-coordinate. * * @return The index in the data buffer that stores the pixel at (x, y). + * + * @see #getBitOffset(int) */ public int getOffset(int x, int y) { - return scanlineStride * y + ((dataBitOffset + x*numberOfBits) / elemBits); + return scanlineStride * y + ((dataBitOffset + x * numberOfBits) / elemBits); } /** @@ -247,7 +249,7 @@ public class MultiPixelPackedSampleModel extends SampleModel */ public int getBitOffset(int x) { - return (dataBitOffset + x*numberOfBits) % elemBits; + return (dataBitOffset + x * numberOfBits) % elemBits; } /** @@ -331,35 +333,41 @@ public class MultiPixelPackedSampleModel extends SampleModel * array obj, since there is only one band. If obj is null, a new array of * getTransferType() is created. * - * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>. - * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>. - * @param obj The primitive array to store the pixels into or null to force creation. + * @param x The x-coordinate of the pixel rectangle to store in + * <code>obj</code>. + * @param y The y-coordinate of the pixel rectangle to store in + * <code>obj</code>. + * @param obj The primitive array to store the pixels into or null to force + * creation. * @param data The DataBuffer that is the source of the pixel data. * @return The primitive array containing the pixel data. - * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer) + * @see java.awt.image.SampleModel#getDataElements(int, int, Object, + * DataBuffer) */ - public Object getDataElements(int x, int y, Object obj, - DataBuffer data) + public Object getDataElements(int x, int y, Object obj, DataBuffer data) { int pixel = getSample(x, y, 0, data); switch (getTransferType()) - { - case DataBuffer.TYPE_BYTE: - if (obj == null) obj = new byte[1]; - ((byte[])obj)[0] = (byte)pixel; - return obj; - case DataBuffer.TYPE_USHORT: - if (obj == null) obj = new short[1]; - ((short[])obj)[0] = (short)pixel; - return obj; - case DataBuffer.TYPE_INT: - if (obj == null) obj = new int[1]; - ((int[])obj)[0] = pixel; - return obj; - default: - // Seems like the only sensible thing to do. - throw new ClassCastException(); - } + { + case DataBuffer.TYPE_BYTE: + if (obj == null) + obj = new byte[1]; + ((byte[]) obj)[0] = (byte) pixel; + return obj; + case DataBuffer.TYPE_USHORT: + if (obj == null) + obj = new short[1]; + ((short[]) obj)[0] = (short) pixel; + return obj; + case DataBuffer.TYPE_INT: + if (obj == null) + obj = new int[1]; + ((int[]) obj)[0] = pixel; + return obj; + default: + // Seems like the only sensible thing to do. + throw new ClassCastException(); + } } /** @@ -381,55 +389,13 @@ public class MultiPixelPackedSampleModel extends SampleModel */ public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) { - if (iArray == null) iArray = new int[1]; + if (iArray == null) + iArray = new int[1]; iArray[0] = getSample(x, y, 0, data); - return iArray; } /** - * Returns an array containing the samples for the pixels in the region - * specified by (x, y, w, h) in the specified data buffer. If - * <code>iArray</code> is not <code>null</code>, it will be populated with - * the sample values and returned as the result of this function (this - * avoids allocating a new array instance). - * - * @param x the x-coordinate of the top-left pixel. - * @param y the y-coordinate of the top-left pixel. - * @param w the width of the region of pixels. - * @param h the height of the region of pixels. - * @param iArray an array to populate with the sample values and return as - * the result (if <code>null</code>, a new array will be allocated). - * @param data the data buffer (<code>null</code> not permitted). - * - * @return The pixel sample values. - * - * @throws NullPointerException if <code>data</code> is <code>null</code>. - */ - public int[] getPixels(int x, int y, int w, int h, int[] iArray, - DataBuffer data) - { - int offset = getOffset(x, y); - if (iArray == null) iArray = new int[w*h]; - int outOffset = 0; - for (y=0; y<h; y++) - { - int lineOffset = offset; - for (x=0; x<w;) - { - int samples = data.getElem(lineOffset++); - for (int b=0; b<numElems && x<w; b++) - { - iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b]; - x++; - } - } - offset += scanlineStride; - } - return iArray; - } - - /** * Returns the sample value for the pixel at (x, y) in the specified data * buffer. * @@ -460,66 +426,49 @@ public class MultiPixelPackedSampleModel extends SampleModel * @param y The y-coordinate of the data elements in <code>obj</code>. * @param obj The primitive array containing the data elements to set. * @param data The DataBuffer to store the data elements into. - * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer) */ public void setDataElements(int x, int y, Object obj, DataBuffer data) { int transferType = getTransferType(); - if (getTransferType() != data.getDataType()) - { - throw new IllegalArgumentException("transfer type ("+ - getTransferType()+"), "+ - "does not match data "+ - "buffer type (" + - data.getDataType() + - ")."); - } - - int offset = getOffset(x, y); - 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; - } - default: - throw new ClassCastException("Unsupported data type"); - } + switch (transferType) + { + case DataBuffer.TYPE_BYTE: + { + byte[] in = (byte[]) obj; + setSample(x, y, 0, in[0] & 0xFF, data); + return; + } + case DataBuffer.TYPE_USHORT: + { + short[] in = (short[]) obj; + setSample(x, y, 0, in[0] & 0xFFFF, data); + return; + } + case DataBuffer.TYPE_INT: + { + int[] in = (int[]) obj; + setSample(x, y, 0, in[0], data); + return; + } + default: + throw new ClassCastException("Unsupported data type"); + } } 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); + String msg = "While writing data elements" + + ", x=" + x + ", y=" + y + + ", width=" + width + ", height=" + height + + ", scanlineStride=" + scanlineStride + + ", offset=" + getOffset(x, y) + + ", data.getSize()=" + data.getSize() + + ", data.getOffset()=" + data.getOffset() + + ": " + aioobe; + throw new ArrayIndexOutOfBoundsException(msg); } - } + } /** * Sets the sample value for the pixel at (x, y) in the specified data diff --git a/java/awt/image/Raster.java b/java/awt/image/Raster.java index 4af958a17..160f8be8b 100644 --- a/java/awt/image/Raster.java +++ b/java/awt/image/Raster.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2003 Free Software Foundation +/* Copyright (C) 2000, 2002, 2003, 2006, Free Software Foundation This file is part of GNU Classpath. @@ -41,39 +41,80 @@ import java.awt.Point; import java.awt.Rectangle; /** + * A rectangular collection of pixels composed from a {@link DataBuffer} which + * stores the pixel values, and a {@link SampleModel} which is used to retrieve + * the pixel values. + * * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) */ public class Raster { + /** The sample model used to access the pixel values. */ protected SampleModel sampleModel; + + /** The data buffer used to store the pixel values. */ protected DataBuffer dataBuffer; + + /** The x-coordinate of the top left corner of the raster. */ protected int minX; + + /** The y-coordinate of the top left corner of the raster. */ protected int minY; + + /** The width of the raster. */ protected int width; + + /** The height of the raster. */ protected int height; + protected int sampleModelTranslateX; + protected int sampleModelTranslateY; + + /** The number of bands. */ protected int numBands; + protected int numDataElements; + + /** The raster's parent. */ protected Raster parent; + /** + * Creates a new raster. + * + * @param sampleModel the sample model. + * @param origin the origin. + */ protected Raster(SampleModel sampleModel, Point origin) { this(sampleModel, sampleModel.createDataBuffer(), origin); } + /** + * Creates a new raster. + * + * @param sampleModel the sample model. + * @param dataBuffer the data buffer. + * @param origin the origin. + */ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer, - Point origin) + Point origin) { - this(sampleModel, dataBuffer, - new Rectangle(origin.x, origin.y, - sampleModel.getWidth(), sampleModel.getHeight()), - origin, null); + this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y, + sampleModel.getWidth(), sampleModel.getHeight()), origin, null); } + /** + * Creates a new raster. + * + * @param sampleModel the sample model. + * @param dataBuffer the data buffer. + * @param aRegion the raster's bounds. + * @param sampleModelTranslate the translation (<code>null</code> permitted). + * @param parent the raster's parent. + */ protected Raster(SampleModel sampleModel, DataBuffer dataBuffer, - Rectangle aRegion, - Point sampleModelTranslate, Raster parent) + Rectangle aRegion, Point sampleModelTranslate, Raster parent) { this.sampleModel = sampleModel; this.dataBuffer = dataBuffer; @@ -95,70 +136,127 @@ public class Raster this.parent = parent; } + /** + * Creates an interleaved raster using the specified data type. + * + * @param dataType the data type. + * @param w the width. + * @param h the height. + * @param bands the number of bands. + * @param location + * + * @return The new raster. + */ public static WritableRaster createInterleavedRaster(int dataType, - int w, int h, - int bands, - Point location) + 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; + for (int b = 0; b < bands; b++) + bandOffsets[b] = b; - int scanlineStride = bands*w; + int scanlineStride = bands * w; return createInterleavedRaster(dataType, w, h, scanlineStride, bands, - bandOffsets, location); + 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); + /** + * Creates an interleaved raster. + * + * @param dataType the data type. + * @param w the width. + * @param h the height. + * @param scanlineStride the number of data elements from a sample on one + * row to the corresponding sample on the next row. + * @param pixelStride the number of elements from a sample in one pixel to + * the corresponding sample in the next pixel. + * @param bandOffsets the band offsets. + * @param location + * + * @return The new raster. + */ + 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) + /** + * Creates a new banded raster. + * + * @param dataType the data type. + * @param w the width. + * @param h the height. + * @param bands the number of bands. + * @param location + * + * @return The new raster. + */ + public static WritableRaster createBandedRaster(int dataType, int w, int h, + int bands, Point location) { SampleModel sm = new BandedSampleModel(dataType, w, h, bands); return createWritableRaster(sm, location); } - public static WritableRaster createBandedRaster(int dataType, - int w, int h, - int scanlineStride, - int[] bankIndices, - int[] bandOffsets, - Point location) + /** + * Creates a new banded raster. + * + * @param dataType the data type. + * @param w the width. + * @param h the height. + * @param scanlineStride the number of data elements from a sample on one + * row to the corresponding sample on the next row. + * @param bankIndices the index for each bank. + * @param bandOffsets the offset for each band. + * @param location + * + * @return The new raster. + */ + public static WritableRaster createBandedRaster(int dataType, int w, int h, + int scanlineStride, int[] bankIndices, int[] bandOffsets, Point location) { SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride, - bankIndices, bandOffsets); + bankIndices, bandOffsets); return createWritableRaster(sm, location); } - public static WritableRaster createPackedRaster(int dataType, - int w, int h, - int[] bandMasks, - Point location) + /** + * Creates a new packed raster. + * + * @param dataType the data type. + * @param w the width. + * @param h the height. + * @param bandMasks the bit mask for each band. + * @param location + * + * @return The new raster. + */ + public static WritableRaster createPackedRaster(int dataType, int w, int h, + int[] bandMasks, Point location) { - SampleModel sm = new SinglePixelPackedSampleModel(dataType, - w, h, - bandMasks); + SampleModel sm = new SinglePixelPackedSampleModel(dataType, w, h, + bandMasks); return createWritableRaster(sm, location); } + /** + * Creates a new raster. + * + * @param dataType the data type. + * @param w the width. + * @param h the height. + * @param bands the number of bands. + * @param bitsPerBand the number of bits per band. + * @param location + * + * @return The new raster. + */ public static WritableRaster createPackedRaster(int dataType, - int w, int h, - int bands, int bitsPerBand, - Point location) + int w, int h, int bands, int bitsPerBand, Point location) { if (bands <= 0 || (bands * bitsPerBand > getTypeBits(dataType))) throw new IllegalArgumentException(); @@ -166,135 +264,238 @@ public class Raster SampleModel sm; if (bands == 1) - sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand); + sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand); else { - int[] bandMasks = new int[bands]; - int mask = 0x1; - for (int bits = bitsPerBand; --bits != 0;) - mask = (mask << 1) | 0x1; - for (int i = 0; i < bands; i++) - { - bandMasks[i] = mask; - mask <<= bitsPerBand; - } - - sm = new SinglePixelPackedSampleModel(dataType, w, h, bandMasks); + int[] bandMasks = new int[bands]; + int mask = 0x1; + for (int bits = bitsPerBand; --bits != 0;) + mask = (mask << 1) | 0x1; + for (int i = 0; i < bands; i++) + { + bandMasks[i] = mask; + mask <<= bitsPerBand; + } + + 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) + /** + * Creates a new interleaved raster. + * + * @param dataBuffer the data buffer. + * @param w the width. + * @param h the height. + * @param scanlineStride the number of data elements from a sample on one + * row to the corresponding sample on the next row. + * @param pixelStride the number of elements from a sample in one pixel to + * the corresponding sample in the next pixel. + * @param bandOffsets the offset for each band. + * @param location + * + * @return The new raster. + */ + 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); + 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) + /** + * Creates a new banded raster. + * + * @param dataBuffer the data buffer. + * @param w the width. + * @param h the height. + * @param scanlineStride the number of data elements from a sample on one + * row to the corresponding sample on the next row. + * @param bankIndices the index for each bank. + * @param bandOffsets the band offsets. + * @param location + * + * @return The new raster. + */ + public static WritableRaster createBandedRaster(DataBuffer dataBuffer, + int w, int h, int scanlineStride, int[] bankIndices, int[] bandOffsets, + Point location) { SampleModel sm = new BandedSampleModel(dataBuffer.getDataType(), - w, h, scanlineStride, - bankIndices, bandOffsets); + w, h, scanlineStride, bankIndices, bandOffsets); return createWritableRaster(sm, dataBuffer, location); } - public static WritableRaster - createPackedRaster(DataBuffer dataBuffer, - int w, int h, - int scanlineStride, - int[] bandMasks, - Point location) + /** + * Creates a new packed raster. + * + * @param dataBuffer the data buffer. + * @param w the width. + * @param h the height. + * @param scanlineStride the number of data elements from a sample on one + * row to the corresponding sample on the next row. + * @param bandMasks the bit mask for each band. + * @param location + * + * @return The new raster. + */ + 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); + SampleModel sm = new SinglePixelPackedSampleModel(dataBuffer.getDataType(), + w, h, scanlineStride, bandMasks); return createWritableRaster(sm, dataBuffer, location); } - public static WritableRaster - createPackedRaster(DataBuffer dataBuffer, - int w, int h, - int bitsPerPixel, - Point location) - { - SampleModel sm = - new MultiPixelPackedSampleModel(dataBuffer.getDataType(), - w, h, - bitsPerPixel); + /** + * Creates a new packed raster. + * + * @param dataBuffer the data buffer. + * @param w the width. + * @param h the height. + * @param bitsPerPixel the number of bits per pixel. + * @param location + * + * @return The new raster. + */ + public static WritableRaster createPackedRaster(DataBuffer dataBuffer, + int w, int h, int bitsPerPixel, Point location) + { + SampleModel sm = new MultiPixelPackedSampleModel(dataBuffer.getDataType(), + w, h, bitsPerPixel); return createWritableRaster(sm, dataBuffer, location); } + /** + * Creates a new raster. + * + * @param sm the sample model. + * @param db the data buffer. + * @param location + * + * @return The new raster. + */ public static Raster createRaster(SampleModel sm, DataBuffer db, - Point location) + Point location) { return new Raster(sm, db, location); } + /** + * Creates a new writable raster. + * + * @param sm the sample model. + * @param location + * + * @return The new writable raster. + */ public static WritableRaster createWritableRaster(SampleModel sm, - Point location) + Point location) { return new WritableRaster(sm, location); } + /** + * Creates a new writable raster. + * + * @param sm the sample model. + * @param db the data buffer. + * @param location + * + * @return The new writable raster. + */ public static WritableRaster createWritableRaster(SampleModel sm, - DataBuffer db, - Point location) + DataBuffer db, Point location) { return new WritableRaster(sm, db, location); } + /** + * Returns the raster's parent. + * + * @return The raster's parent. + */ public Raster getParent() { return parent; } + /** + * Returns the x-translation. + * + * @return The x-translation. + */ public final int getSampleModelTranslateX() { return sampleModelTranslateX; } + /** + * Returns the y-translation. + * + * @return The y-translation. + */ public final int getSampleModelTranslateY() { return sampleModelTranslateY; } + /** + * Creates a new writable raster that is compatible with this raster. + * + * @return A new writable raster. + */ public WritableRaster createCompatibleWritableRaster() { return new WritableRaster(getSampleModel(), new Point(minX, minY)); } + /** + * Creates a new writable raster that is compatible with this raster. + * + * @param w the width. + * @param h the height. + * + * @return A new writable raster. + */ public WritableRaster createCompatibleWritableRaster(int w, int h) { return createCompatibleWritableRaster(minX, minY, w, h); } + /** + * Creates a new writable raster that is compatible with this raster, with + * the specified bounds. + * + * @param rect the raster bounds. + * + * @return A new writable raster. + */ public WritableRaster createCompatibleWritableRaster(Rectangle rect) { return createCompatibleWritableRaster(rect.x, rect.y, - rect.width, rect.height); + rect.width, rect.height); } + /** + * Creates a new writable raster that is compatible with this raster, with + * the specified bounds. + * + * @param x the x-coordinate of the top-left corner of the raster. + * @param y the y-coordinate of the top-left corner of the raster. + * @param w the raster width. + * @param h the raster height. + * + * @return A new writable raster. + */ public WritableRaster createCompatibleWritableRaster(int x, int y, - int w, int h) + int w, int h) { SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h); - return new WritableRaster(sm, sm.createDataBuffer(), - new Point(x, y)); + return new WritableRaster(sm, sm.createDataBuffer(), new Point(x, y)); } public Raster createTranslatedChild(int childMinX, int childMinY) { @@ -302,15 +503,13 @@ public class Raster int tcy = sampleModelTranslateY - minY + childMinY; return new Raster(sampleModel, dataBuffer, - new Rectangle(childMinX, childMinY, - width, height), - new Point(tcx, tcy), - this); + 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) + int height, int childMinX, int childMinY, + int[] bandList) { /* FIXME: Throw RasterFormatException if child bounds extends beyond the bounds of this raster. */ @@ -343,38 +542,67 @@ public class Raster */ return new Raster(sm, dataBuffer, - new Rectangle(childMinX, childMinY, - width, height), - new Point(sampleModelTranslateX+childMinX-parentX, - sampleModelTranslateY+childMinY-parentY), - this); + new Rectangle(childMinX, childMinY, width, height), + new Point(sampleModelTranslateX + childMinX - parentX, + sampleModelTranslateY + childMinY - parentY), + this); } + /** + * Returns a new rectangle containing the bounds of this raster. + * + * @return A new rectangle containing the bounds of this raster. + */ public Rectangle getBounds() { return new Rectangle(minX, minY, width, height); } + /** + * Returns the x-coordinate of the top left corner of the raster. + * + * @return The x-coordinate of the top left corner of the raster. + */ public final int getMinX() { return minX; } + /** + * Returns the t-coordinate of the top left corner of the raster. + * + * @return The t-coordinate of the top left corner of the raster. + */ public final int getMinY() { return minY; } + /** + * Returns the width of the raster. + * + * @return The width of the raster. + */ public final int getWidth() { return width; } + /** + * Returns the height of the raster. + * + * @return The height of the raster. + */ public final int getHeight() { return height; } + /** + * Returns the number of bands for this raster. + * + * @return The number of bands. + */ public final int getNumBands() { return numBands; @@ -384,17 +612,34 @@ public class Raster { return numDataElements; } - + + /** + * Returns the transfer type for the raster (this is determined by the + * raster's sample model). + * + * @return The transfer type. + */ public final int getTransferType() { return sampleModel.getTransferType(); } + /** + * Returns the data buffer that stores the pixel data for this raster. + * + * @return The data buffer. + */ public DataBuffer getDataBuffer() { return dataBuffer; } + /** + * Returns the sample model that accesses the data buffer (to extract pixel + * data) for this raster. + * + * @return The sample model. + */ public SampleModel getSampleModel() { return sampleModel; @@ -402,112 +647,275 @@ public class Raster public Object getDataElements(int x, int y, Object outData) { - return sampleModel.getDataElements(x-sampleModelTranslateX, - y-sampleModelTranslateY, - outData, dataBuffer); + return sampleModel.getDataElements(x - sampleModelTranslateX, + y - sampleModelTranslateY, outData, dataBuffer); } - public Object getDataElements(int x, int y, int w, int h, - Object outData) + public Object getDataElements(int x, int y, int w, int h, Object outData) { - return sampleModel.getDataElements(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, outData, dataBuffer); + return sampleModel.getDataElements(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, outData, dataBuffer); } + /** + * Returns an array containing the samples for the pixel at (x, y) in the + * raster. If <code>iArray</code> is not <code>null</code>, it will be + * populated with the sample values and returned as the result of + * this function (this avoids allocating a new array instance). + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param iArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The pixel sample values. + */ public int[] getPixel(int x, int y, int[] iArray) { - return sampleModel.getPixel(x-sampleModelTranslateX, - y-sampleModelTranslateY, - iArray, dataBuffer); + return sampleModel.getPixel(x - sampleModelTranslateX, + y - sampleModelTranslateY, iArray, dataBuffer); } + /** + * Returns an array containing the samples for the pixel at (x, y) in the + * raster. If <code>fArray</code> is not <code>null</code>, it will be + * populated with the sample values and returned as the result of + * this function (this avoids allocating a new array instance). + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param fArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The pixel sample values. + */ public float[] getPixel(int x, int y, float[] fArray) { - return sampleModel.getPixel(x-sampleModelTranslateX, - y-sampleModelTranslateY, - fArray, dataBuffer); + return sampleModel.getPixel(x - sampleModelTranslateX, + y - sampleModelTranslateY, fArray, dataBuffer); } + /** + * Returns an array containing the samples for the pixel at (x, y) in the + * raster. If <code>dArray</code> is not <code>null</code>, it will be + * populated with the sample values and returned as the result of + * this function (this avoids allocating a new array instance). + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param dArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The pixel sample values. + */ public double[] getPixel(int x, int y, double[] dArray) { - return sampleModel.getPixel(x-sampleModelTranslateX, - y-sampleModelTranslateY, - dArray, dataBuffer); + return sampleModel.getPixel(x - sampleModelTranslateX, + y - sampleModelTranslateY, dArray, dataBuffer); } + /** + * Returns an array containing the samples for the pixels in the region + * specified by (x, y, w, h) in the raster. The array is ordered by pixels + * (that is, all the samples for the first pixel are grouped together, + * followed by all the samples for the second pixel, and so on). + * If <code>iArray</code> is not <code>null</code>, it will be populated + * with the sample values and returned as the result of this function (this + * avoids allocating a new array instance). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param iArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The pixel sample values. + */ public int[] getPixels(int x, int y, int w, int h, int[] iArray) { - return sampleModel.getPixels(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, iArray, dataBuffer); + return sampleModel.getPixels(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, iArray, dataBuffer); } - public float[] getPixels(int x, int y, int w, int h, - float[] fArray) + /** + * Returns an array containing the samples for the pixels in the region + * specified by (x, y, w, h) in the raster. The array is ordered by pixels + * (that is, all the samples for the first pixel are grouped together, + * followed by all the samples for the second pixel, and so on). + * If <code>fArray</code> is not <code>null</code>, it will be populated + * with the sample values and returned as the result of this function (this + * avoids allocating a new array instance). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param fArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The pixel sample values. + */ + public float[] getPixels(int x, int y, int w, int h, float[] fArray) { - return sampleModel.getPixels(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, fArray, dataBuffer); + return sampleModel.getPixels(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, fArray, dataBuffer); } - public double[] getPixels(int x, int y, int w, int h, - double[] dArray) + /** + * Returns an array containing the samples for the pixels in the region + * specified by (x, y, w, h) in the raster. The array is ordered by pixels + * (that is, all the samples for the first pixel are grouped together, + * followed by all the samples for the second pixel, and so on). + * If <code>dArray</code> is not <code>null</code>, it will be populated + * with the sample values and returned as the result of this function (this + * avoids allocating a new array instance). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param dArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The pixel sample values. + */ + public double[] getPixels(int x, int y, int w, int h, double[] dArray) { - return sampleModel.getPixels(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, dArray, dataBuffer); + return sampleModel.getPixels(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, dArray, dataBuffer); } + /** + * Returns the sample value for the pixel at (x, y) in the raster. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param b the band (in the range <code>0</code> to + * <code>getNumBands() - 1</code>). + * + * @return The sample value. + */ public int getSample(int x, int y, int b) { - return sampleModel.getSample(x-sampleModelTranslateX, - y-sampleModelTranslateY, - b, dataBuffer); + return sampleModel.getSample(x - sampleModelTranslateX, + y - sampleModelTranslateY, b, dataBuffer); } + /** + * Returns the sample value for the pixel at (x, y) in the raster. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param b the band (in the range <code>0</code> to + * <code>getNumBands() - 1</code>). + * + * @return The sample value. + * + * @see #getSample(int, int, int) + */ public float getSampleFloat(int x, int y, int b) { - return sampleModel.getSampleFloat(x-sampleModelTranslateX, - y-sampleModelTranslateY, - b, dataBuffer); + return sampleModel.getSampleFloat(x - sampleModelTranslateX, + y - sampleModelTranslateY, b, dataBuffer); } + /** + * Returns the sample value for the pixel at (x, y) in the raster. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param b the band (in the range <code>0</code> to + * <code>getNumBands() - 1</code>). + * + * @return The sample value. + * + * @see #getSample(int, int, int) + */ public double getSampleDouble(int x, int y, int b) { - return sampleModel.getSampleDouble(x-sampleModelTranslateX, - y-sampleModelTranslateY, - b, dataBuffer); + return sampleModel.getSampleDouble(x - sampleModelTranslateX, + y - sampleModelTranslateY, b, dataBuffer); } + /** + * Returns an array containing the samples from one band for the pixels in + * the region specified by (x, y, w, h) in the raster. If + * <code>iArray</code> is not <code>null</code>, it will be + * populated with the sample values and returned as the result of this + * function (this avoids allocating a new array instance). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param b the band (in the range <code>0</code> to + * </code>getNumBands() - 1</code>). + * @param iArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The sample values. + */ public int[] getSamples(int x, int y, int w, int h, int b, - int[] iArray) + int[] iArray) { - return sampleModel.getSamples(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, b, iArray, dataBuffer); + 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); + /** + * Returns an array containing the samples from one band for the pixels in + * the region specified by (x, y, w, h) in the raster. If + * <code>fArray</code> is not <code>null</code>, it will be + * populated with the sample values and returned as the result of this + * function (this avoids allocating a new array instance). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param b the band (in the range <code>0</code> to + * </code>getNumBands() - 1</code>). + * @param fArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The sample values. + */ + 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) + /** + * Returns an array containing the samples from one band for the pixels in + * the region specified by (x, y, w, h) in the raster. If + * <code>dArray</code> is not <code>null</code>, it will be + * populated with the sample values and returned as the result of this + * function (this avoids allocating a new array instance). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param b the band (in the range <code>0</code> to + * </code>getNumBands() - 1</code>). + * @param dArray an array to populate with the sample values and return as + * the result (if <code>null</code>, a new array will be allocated). + * + * @return The sample values. + */ + 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); + return sampleModel.getSamples(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, b, dArray, dataBuffer); } /** - * Create a String representing the stat of this Raster. + * Create a String representing the state of this Raster. + * * @return A String representing the stat of this Raster. - * @see java.lang.Object#toString() */ public String toString() { @@ -524,23 +932,39 @@ public class Raster return result.toString(); } - // Map from datatype to bits + /** + * Returns the number of bits used to represent the specified data type. + * Valid types are: + * <ul> + * <li>{@link DataBuffer#TYPE_BYTE};</li> + * <li>{@link DataBuffer#TYPE_USHORT};</li> + * <li>{@link DataBuffer#TYPE_SHORT};</li> + * <li>{@link DataBuffer#TYPE_INT};</li> + * <li>{@link DataBuffer#TYPE_FLOAT};</li> + * <li>{@link DataBuffer#TYPE_DOUBLE};</li> + * </ul> + * This method returns 0 for invalid data types. + * + * @param dataType the data type. + * + * @return The number of bits used to represent the specified data type. + */ private static int getTypeBits(int dataType) { switch (dataType) { case DataBuffer.TYPE_BYTE: - return 8; + return 8; case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_SHORT: - return 16; + return 16; case DataBuffer.TYPE_INT: case DataBuffer.TYPE_FLOAT: - return 32; + return 32; case DataBuffer.TYPE_DOUBLE: - return 64; + return 64; default: - return 0; + return 0; } } } diff --git a/java/awt/image/RasterOp.java b/java/awt/image/RasterOp.java index e081ca3d2..656370e8b 100644 --- a/java/awt/image/RasterOp.java +++ b/java/awt/image/RasterOp.java @@ -1,5 +1,5 @@ /* RasterOp.java -- - Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation + Copyright (C) 2000, 2002, 2004, 2005, 2006, Free Software Foundation This file is part of GNU Classpath. @@ -42,16 +42,64 @@ import java.awt.RenderingHints; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +/** + * An operation that is performed on one raster (the source) producing a new + * raster (the destination). + */ public interface RasterOp { + /** + * Performs an operation on the source raster, returning the result in a + * writable raster. If <code>dest</code> is <code>null</code>, a new + * <code>WritableRaster</code> will be created by calling the + * {@link #createCompatibleDestRaster(Raster)} method. If <code>dest</code> + * is not <code>null</code>, the result is written to <code>dest</code> then + * returned (this avoids creating a new <code>WritableRaster</code> each + * time this method is called). + * + * @param src the source raster. + * @param dest the destination raster (<code>null</code> permitted). + * + * @return The filtered raster. + */ WritableRaster filter(Raster src, WritableRaster dest); + /** + * Returns the bounds of the destination raster on the basis of this + * <code>RasterOp</code> being applied to the specified source raster. + * + * @param src the source raster. + * + * @return The destination bounds. + */ Rectangle2D getBounds2D(Raster src); + /** + * Returns a raster that can be used by this <code>RasterOp</code> as the + * destination raster when operating on the specified source raster. + * + * @param src the source raster. + * + * @return A new writable raster that can be used as the destination raster. + */ WritableRaster createCompatibleDestRaster(Raster src); + /** + * Returns the point on the destination raster that corresponds to the given + * point on the source raster. + * + * @param srcPoint the source point. + * @param destPoint the destination point (<code>null</code> permitted). + * + * @return The destination point. + */ Point2D getPoint2D(Point2D srcPoint, Point2D destPoint); + /** + * Returns the rendering hints for this operation. + * + * @return The rendering hints. + */ RenderingHints getRenderingHints(); } diff --git a/java/awt/image/ShortLookupTable.java b/java/awt/image/ShortLookupTable.java index 5915a7939..858818cf2 100644 --- a/java/awt/image/ShortLookupTable.java +++ b/java/awt/image/ShortLookupTable.java @@ -1,5 +1,5 @@ /* ShortLookupTable.java -- Java class for a pixel translation table. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -67,7 +67,13 @@ public class ShortLookupTable extends LookupTable throws IllegalArgumentException { super(offset, data.length); - this.data = data; + + // tests show that Sun's implementation creates a new array to store the + // references from the incoming 'data' array - not sure why, but we'll + // match that behaviour just in case it matters... + this.data = new short[data.length][]; + for (int i = 0; i < data.length; i++) + this.data[i] = data[i]; } /** @@ -77,17 +83,25 @@ public class ShortLookupTable extends LookupTable * table. The same table is applied to all pixel components. * * @param offset Offset to be subtracted. - * @param data Lookup table for all components. + * @param data Lookup table for all components (<code>null</code> not + * permitted). * @exception IllegalArgumentException if offset < 0. */ public ShortLookupTable(int offset, short[] data) throws IllegalArgumentException { super(offset, 1); + if (data == null) + throw new NullPointerException("Null 'data' argument."); this.data = new short[][] {data}; } - /** Return the lookup tables. */ + /** + * Return the lookup tables. This is a reference to the actual table, so + * modifying the contents of the returned array will modify the lookup table. + * + * @return The lookup table. + */ public final short[][] getTable() { return data; @@ -117,11 +131,11 @@ public class ShortLookupTable extends LookupTable dst = new int[src.length]; if (data.length == 1) - for (int i=0; i < src.length; i++) - dst[i] = data[0][src[i] - offset]; + for (int i = 0; i < src.length; i++) + dst[i] = data[0][src[i] - offset]; else - for (int i=0; i < src.length; i++) - dst[i] = data[i][src[i] - offset]; + for (int i = 0; i < src.length; i++) + dst[i] = data[i][src[i] - offset]; return dst; } @@ -142,6 +156,7 @@ public class ShortLookupTable extends LookupTable * @param src Component values of a pixel. * @param dst Destination array for values, or null. * @return Translated values for the pixel. + * */ public short[] lookupPixel(short[] src, short[] dst) throws ArrayIndexOutOfBoundsException @@ -150,11 +165,11 @@ public class ShortLookupTable extends LookupTable dst = new short[src.length]; if (data.length == 1) - for (int i=0; i < src.length; i++) - dst[i] = data[0][((int)src[i]) - offset]; + for (int i = 0; i < src.length; i++) + dst[i] = data[0][((int) src[i]) - offset]; else - for (int i=0; i < src.length; i++) - dst[i] = data[i][((int)src[i]) - offset]; + for (int i = 0; i < src.length; i++) + dst[i] = data[i][((int) src[i]) - offset]; return dst; diff --git a/java/awt/image/SinglePixelPackedSampleModel.java b/java/awt/image/SinglePixelPackedSampleModel.java index 548865a40..a37fc0bba 100644 --- a/java/awt/image/SinglePixelPackedSampleModel.java +++ b/java/awt/image/SinglePixelPackedSampleModel.java @@ -171,7 +171,7 @@ public class SinglePixelPackedSampleModel extends SampleModel */ public int[] getSampleSize() { - return sampleSize; + return (int[]) sampleSize.clone(); } /** @@ -187,6 +187,14 @@ public class SinglePixelPackedSampleModel extends SampleModel return sampleSize[band]; } + /** + * Returns the index in the data buffer that stores the pixel at (x, y). + * + * @param x the x-coordinate. + * @param y the y-coordinate. + * + * @return The index in the data buffer that stores the pixel at (x, y). + */ public int getOffset(int x, int y) { return scanlineStride*y + x; @@ -202,14 +210,34 @@ public class SinglePixelPackedSampleModel extends SampleModel return bitMasks; } + /** + * Returns the number of data elements from a pixel in one row to the + * corresponding pixel in the next row. + * + * @return The scanline stride. + */ public int getScanlineStride() { return scanlineStride; } + /** + * Creates a new <code>SinglePixelPackedSampleModel</code> that accesses + * the specified subset of bands. + * + * @param bands an array containing band indices (<code>null</code> not + * permitted). + * + * @return A new sample model. + * + * @throws NullPointerException if <code>bands</code> is <code>null</code>. + * @throws RasterFormatException if <code>bands.length</code> is greater + * than the number of bands in this model. + */ public SampleModel createSubsetSampleModel(int[] bands) { - // FIXME: Is this the right way to interpret bands? + if (bands.length > numBands) + throw new RasterFormatException("Too many bands."); int numBands = bands.length; @@ -619,6 +647,27 @@ public class SinglePixelPackedSampleModel extends SampleModel } /** + * Returns a hash code for this <code>SinglePixelPackedSampleModel</code>. + * + * @return A hash code. + */ + public int hashCode() + { + // this hash code won't match Sun's, but that shouldn't matter... + int result = 193; + result = 37 * result + dataType; + result = 37 * result + width; + result = 37 * result + height; + result = 37 * result + numBands; + result = 37 * result + scanlineStride; + for (int i = 0; i < bitMasks.length; i++) + result = 37 * result + bitMasks[i]; + for (int i = 0; i < bitOffsets.length; i++) + result = 37 * result + bitOffsets[i]; + return result; + } + + /** * Creates a String with some information about this SampleModel. * @return A String describing this SampleModel. * @see java.lang.Object#toString() diff --git a/java/awt/image/WritableRaster.java b/java/awt/image/WritableRaster.java index 2e5462fd9..473c6fe41 100644 --- a/java/awt/image/WritableRaster.java +++ b/java/awt/image/WritableRaster.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2003 Free Software Foundation +/* Copyright (C) 2000, 2002, 2003, 2006, Free Software Foundation This file is part of GNU Classpath. @@ -41,61 +41,98 @@ import java.awt.Point; import java.awt.Rectangle; /** + * A raster with methods to support updating pixel values. + * * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) */ public class WritableRaster extends Raster { + /** + * Creates a new <code>WritableRaster</code>. + * + * @param sampleModel the sample model. + * @param origin the origin. + */ protected WritableRaster(SampleModel sampleModel, Point origin) { this(sampleModel, sampleModel.createDataBuffer(), origin); } - protected WritableRaster(SampleModel sampleModel, - DataBuffer dataBuffer, Point origin) + /** + * Creates a new <code>WritableRaster</code> instance. + * + * @param sampleModel the sample model. + * @param dataBuffer the data buffer. + * @param origin the origin. + */ + protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer, + Point origin) { this(sampleModel, dataBuffer, - new Rectangle(origin != null ? origin.x : 0, + new Rectangle(origin != null ? origin.x : 0, origin != null ? origin.y : 0, - sampleModel.getWidth(), sampleModel.getHeight()), - origin, - null); + sampleModel.getWidth(), sampleModel.getHeight()), + origin, null); } + /** + * Creates a new <code>WritableRaster</code> instance. + * + * @param sampleModel the sample model. + * @param dataBuffer the data buffer. + * @param aRegion the raster's bounds. + * @param sampleModelTranslate the translation. + * @param parent the parent. + */ protected WritableRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point sampleModelTranslate, - WritableRaster parent) + DataBuffer dataBuffer, + Rectangle aRegion, + Point sampleModelTranslate, + WritableRaster parent) { - super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, - parent); + super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent); } + /** + * Returns the raster's parent, cast as a {@link WritableRaster}. + * + * @return The raster's parent. + */ public WritableRaster getWritableParent() { return (WritableRaster) getParent(); } + /** + * @param childMinX + * @param childMinY + * @return + */ public WritableRaster createWritableTranslatedChild(int childMinX, - int childMinY) + 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); + 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) + /** + * + * @param parentX + * @param parentY + * @param w + * @param h + * @param childMinX + * @param childMinY + * @param bandList + * @return + */ + 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 @@ -106,51 +143,52 @@ public class WritableRaster extends Raster sampleModel : sampleModel.createSubsetSampleModel(bandList); - return new - WritableRaster(sm, dataBuffer, - new Rectangle(childMinX, childMinY, - w, h), - new Point(sampleModelTranslateX+childMinX-parentX, - sampleModelTranslateY+childMinY-parentY), - this); + 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); + 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); + 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) + public void setDataElements(int x, int y, int w, int h, Object inData) { - sampleModel.setDataElements(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, inData, dataBuffer); + sampleModel.setDataElements(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, inData, dataBuffer); } + /** + * + * @param srcRaster + */ public void setRect(Raster srcRaster) { setRect(0, 0, srcRaster); } + /** + * + * @param dx + * @param dy + * @param srcRaster + */ public void setRect(int dx, int dy, Raster srcRaster) { - Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX()+dx, - srcRaster.getMinY()+dy, - srcRaster.getWidth(), - srcRaster.getHeight()); - + Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX() + dx, + srcRaster.getMinY() + dy, srcRaster.getWidth(), srcRaster.getHeight()); + Rectangle target = getBounds().intersection(targetUnclipped); if (target.isEmpty()) return; @@ -169,97 +207,225 @@ public class WritableRaster extends Raster But this is probably not the place to consider such optimizations.*/ - int[] pixels = srcRaster.getPixels(sx, sy, - target.width, target.height, - (int[]) null); + int[] pixels = srcRaster.getPixels(sx, sy, target.width, target.height, + (int[]) null); setPixels(target.x, target.y, target.width, target.height, pixels); } + /** + * Sets the samples for the pixel at (x, y) in the raster to the specified + * values. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param iArray the sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>iArray</code> is <code>null</code>. + */ public void setPixel(int x, int y, int[] iArray) { - sampleModel.setPixel(x-sampleModelTranslateX, - y-sampleModelTranslateY, - iArray, dataBuffer); + sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY, + iArray, dataBuffer); } + /** + * Sets the samples for the pixel at (x, y) in the raster to the specified + * values. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param fArray the sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>fArray</code> is <code>null</code>. + */ public void setPixel(int x, int y, float[] fArray) { - sampleModel.setPixel(x-sampleModelTranslateX, - y-sampleModelTranslateY, - fArray, dataBuffer); + sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY, + fArray, dataBuffer); } + /** + * Sets the samples for the pixel at (x, y) in the raster to the specified + * values. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param dArray the sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>dArray</code> is <code>null</code>. + */ public void setPixel(int x, int y, double[] dArray) { - sampleModel.setPixel(x-sampleModelTranslateX, - y-sampleModelTranslateY, - dArray, dataBuffer); + sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY, + dArray, dataBuffer); } + /** + * Sets the sample values for the pixels in the region specified by + * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all + * the samples for the first pixel are grouped together, followed by all the + * samples for the second pixel, and so on). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param iArray the pixel sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>iArray</code> is <code>null</code>. + */ public void setPixels(int x, int y, int w, int h, int[] iArray) { - sampleModel.setPixels(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, iArray, dataBuffer); + sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY, + w, h, iArray, dataBuffer); } + /** + * Sets the sample values for the pixels in the region specified by + * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all + * the samples for the first pixel are grouped together, followed by all the + * samples for the second pixel, and so on). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param fArray the pixel sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>fArray</code> is <code>null</code>. + */ public void setPixels(int x, int y, int w, int h, float[] fArray) { - sampleModel.setPixels(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, fArray, dataBuffer); + sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY, + w, h, fArray, dataBuffer); } + /** + * Sets the sample values for the pixels in the region specified by + * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all + * the samples for the first pixel are grouped together, followed by all the + * samples for the second pixel, and so on). + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param dArray the pixel sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>dArray</code> is <code>null</code>. + */ public void setPixels(int x, int y, int w, int h, double[] dArray) { - sampleModel.setPixels(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, dArray, dataBuffer); + sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY, + w, h, dArray, dataBuffer); } + /** + * Sets the sample value for a band for the pixel at (x, y) in the raster. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param b the band (in the range <code>0</code> to + * <code>getNumBands() - 1</code>). + * @param s the sample value. + */ public void setSample(int x, int y, int b, int s) { - sampleModel.setSample(x-sampleModelTranslateX, - y-sampleModelTranslateY, - b, s, dataBuffer); + sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY, + b, s, dataBuffer); } + /** + * Sets the sample value for a band for the pixel at (x, y) in the raster. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param b the band (in the range <code>0</code> to + * <code>getNumBands() - 1</code>). + * @param s the sample value. + */ public void setSample(int x, int y, int b, float s) { - sampleModel.setSample(x-sampleModelTranslateX, - y-sampleModelTranslateY, - b, s, dataBuffer); + sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY, + b, s, dataBuffer); } + /** + * Sets the sample value for a band for the pixel at (x, y) in the raster. + * + * @param x the x-coordinate of the pixel. + * @param y the y-coordinate of the pixel. + * @param b the band (in the range <code>0</code> to + * <code>getNumBands() - 1</code>). + * @param s the sample value. + */ public void setSample(int x, int y, int b, double s) { - sampleModel.setSample(x-sampleModelTranslateX, - y-sampleModelTranslateY, - b, s, dataBuffer); + sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY, + b, s, dataBuffer); } + /** + * Sets the sample values for one band for the pixels in the region + * specified by (x, y, w, h) in the raster. + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param b the band (in the range <code>0</code> to + * </code>getNumBands() - 1</code>). + * @param iArray the sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>iArray</code> is <code>null</code>. + */ public void setSamples(int x, int y, int w, int h, int b, - int[] iArray) + int[] iArray) { - sampleModel.setSamples(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, b, iArray, dataBuffer); + sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY, + w, h, b, iArray, dataBuffer); } + /** + * Sets the sample values for one band for the pixels in the region + * specified by (x, y, w, h) in the raster. + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param b the band (in the range <code>0</code> to + * </code>getNumBands() - 1</code>). + * @param fArray the sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>fArray</code> is <code>null</code>. + */ public void setSamples(int x, int y, int w, int h, int b, - float[] fArray) + float[] fArray) { - sampleModel.setSamples(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, b, fArray, dataBuffer); + sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY, + w, h, b, fArray, dataBuffer); } + /** + * Sets the sample values for one band for the pixels in the region + * specified by (x, y, w, h) in the raster. + * + * @param x the x-coordinate of the top-left pixel. + * @param y the y-coordinate of the top-left pixel. + * @param w the width of the region of pixels. + * @param h the height of the region of pixels. + * @param b the band (in the range <code>0</code> to + * </code>getNumBands() - 1</code>). + * @param dArray the sample values (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>dArray</code> is <code>null</code>. + */ public void setSamples(int x, int y, int w, int h, int b, - double[] dArray) + double[] dArray) { - sampleModel.setSamples(x-sampleModelTranslateX, - y-sampleModelTranslateY, - w, h, b, dArray, dataBuffer); + sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY, + w, h, b, dArray, dataBuffer); } } diff --git a/java/lang/Iterable.java b/java/lang/Iterable.java index 38f478ba7..ea593e88e 100644 --- a/java/lang/Iterable.java +++ b/java/lang/Iterable.java @@ -38,7 +38,8 @@ exception statement from your version. */ package java.lang; -import java.util.Iterator; +// We only need Iterator, but we import * to support lib/mkcollections.pl +import java.util.*; /** * This interface is used to indicate that a given class can be diff --git a/java/lang/StrictMath.java b/java/lang/StrictMath.java index 548a6f1c1..7fd37df8b 100644 --- a/java/lang/StrictMath.java +++ b/java/lang/StrictMath.java @@ -1,5 +1,5 @@ /* java.lang.StrictMath -- common mathematical functions, strict Java - Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1998, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -633,6 +633,131 @@ public final strictfp class StrictMath } /** + * Returns the lower two words of a long. This is intended to be + * used like this: + * <code>getLowDWord(Double.doubleToLongBits(x))</code>. + */ + private static int getLowDWord(long x) + { + return (int) (x & 0x00000000ffffffffL); + } + + /** + * Returns the higher two words of a long. This is intended to be + * used like this: + * <code>getHighDWord(Double.doubleToLongBits(x))</code>. + */ + private static int getHighDWord(long x) + { + return (int) ((x & 0xffffffff00000000L) >> 32); + } + + /** + * Returns a double with the IEEE754 bit pattern given in the lower + * and higher two words <code>lowDWord</code> and <code>highDWord</code>. + */ + private static double buildDouble(int lowDWord, int highDWord) + { + return Double.longBitsToDouble((((long) highDWord & 0xffffffffL) << 32) + | ((long) lowDWord & 0xffffffffL)); + } + + /** + * Returns the cube root of <code>x</code>. The sign of the cube root + * is equal to the sign of <code>x</code>. + * + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is positive + * infinity.</li> + * <li>If the argument is negative infinity, the result is negative + * infinity.</li> + * <li>If the argument is zero, the result is zero with the same + * sign as the argument.</li> + * </ul> + * + * @param x the number to take the cube root of + * @return the cube root of <code>x</code> + * @see #sqrt(double) + * + * @since 1.5 + */ + public static double cbrt(double x) + { + boolean negative = (x < 0); + double r; + double s; + double t; + double w; + + long bits; + int l; + int h; + + // handle the special cases + if (x != x) + return Double.NaN; + if (x == Double.POSITIVE_INFINITY) + return Double.POSITIVE_INFINITY; + if (x == Double.NEGATIVE_INFINITY) + return Double.NEGATIVE_INFINITY; + if (x == 0) + return x; + + x = abs(x); + bits = Double.doubleToLongBits(x); + + if (bits < 0x0010000000000000L) // subnormal number + { + t = TWO_54; + t *= x; + + // __HI(t)=__HI(t)/3+B2; + bits = Double.doubleToLongBits(t); + h = getHighDWord(bits); + l = getLowDWord(bits); + + h = h / 3 + CBRT_B2; + + t = buildDouble(l, h); + } + else + { + // __HI(t)=__HI(x)/3+B1; + h = getHighDWord(bits); + l = 0; + + h = h / 3 + CBRT_B1; + t = buildDouble(l, h); + } + + // new cbrt to 23 bits + r = t * t / x; + s = CBRT_C + r * t; + t *= CBRT_G + CBRT_F / (s + CBRT_E + CBRT_D / s); + + // chopped to 20 bits and make it larger than cbrt(x) + bits = Double.doubleToLongBits(t); + h = getHighDWord(bits); + + // __LO(t)=0; + // __HI(t)+=0x00000001; + l = 0; + h += 1; + t = buildDouble(l, h); + + // one step newton iteration to 53 bits with error less than 0.667 ulps + s = t * t; // t * t is exact + r = x / s; + w = t + t; + r = (r - t) / (w + r); // r - s is exact + t = t + t * r; + + return negative ? -t : t; + } + + /** * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the * argument is NaN, the result is NaN; if the argument is positive infinity, * the result is positive infinity; and if the argument is negative @@ -1429,6 +1554,23 @@ public final strictfp class StrictMath AT10 = 0.016285820115365782; // Long bits 0x3f90ad3ae322da11L. /** + * Constants for computing {@link #cbrt(double)}. + */ + private static final int + CBRT_B1 = 715094163, // B1 = (682-0.03306235651)*2**20 + CBRT_B2 = 696219795; // B2 = (664-0.03306235651)*2**20 + + /** + * Constants for computing {@link #cbrt(double)}. + */ + private static final double + CBRT_C = 5.42857142857142815906e-01, // Long bits 0x3fe15f15f15f15f1L + CBRT_D = -7.05306122448979611050e-01, // Long bits 0xbfe691de2532c834L + CBRT_E = 1.41428571428571436819e+00, // Long bits 0x3ff6a0ea0ea0ea0fL + CBRT_F = 1.60714285714285720630e+00, // Long bits 0x3ff9b6db6db6db6eL + CBRT_G = 3.57142857142857150787e-01; // Long bits 0x3fd6db6db6db6db7L + + /** * Helper function for reducing an angle to a multiple of pi/2 within * [-pi/4, pi/4]. * diff --git a/java/lang/management/MemoryMXBean.java b/java/lang/management/MemoryMXBean.java index 33d211c9b..4d9e5ff1c 100644 --- a/java/lang/management/MemoryMXBean.java +++ b/java/lang/management/MemoryMXBean.java @@ -70,6 +70,34 @@ package java.lang.management; * either change (either expanding or contracting) or stay * the same. * </p> + * <h2>Notifications</h2> + * <p> + * Implementations of this interface also conform to the + * {@link javax.management.NotificationEmitter} interface, + * and supply two notifications reflecting memory usage. + * These notifications occur when a usage threshold is + * exceeded; for more details of these, see the documentation + * of {@link MemoryPoolMXBean}. If threshold monitoring + * is supported, then a notification will be emitted each time + * the threshold is crossed. Another notification will not + * be emitted unless the usage level has dropped below the + * threshold again in the meantime. + * </p> + * <p> + * The emitted notifications are instances of + * {@link javax.management.Notification}, with a type of + * either + * {@link java.lang.management.MemoryNotificationInfo#MEMORY_THRESHOLD_EXCEEDED} + * or + * {@link java.lang.management.MemoryNotificationInfo#MEMORY_COLLECTION_THRESHOLD_EXCEEDED} + * (depending on whether the notification refers to the general + * usage threshold or the garbage collection threshold) and an instance + * of {@link java.lang.management.MemoryNotificationInfo} contained + * in the user data section. This is wrapped inside an instance + * of {@link javax.management.openmbean.CompositeData}, as explained + * in the documentation for + * {@link java.lang.management.MemoryNotificationInfo}. + * </p> * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 diff --git a/java/lang/management/MemoryNotificationInfo.java b/java/lang/management/MemoryNotificationInfo.java index c97fe6bb5..adb38b06f 100644 --- a/java/lang/management/MemoryNotificationInfo.java +++ b/java/lang/management/MemoryNotificationInfo.java @@ -37,10 +37,10 @@ exception statement from your version. */ package java.lang.management; +import gnu.java.lang.management.MemoryMXBeanImpl; + import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; import javax.management.openmbean.SimpleType; /** @@ -168,31 +168,7 @@ public class MemoryNotificationInfo return null; CompositeType type = data.getCompositeType(); ThreadInfo.checkAttribute(type, "poolName", SimpleType.STRING); - try - { - CompositeType uType = - new CompositeType(MemoryUsage.class.getName(), - "Describes the usage levels of a pool", - new String[] { "init", "used", - "committed", "max" - }, - new String[] { "Initial level", - "Used level", - "Committed level", - "Maximum level" - }, - new OpenType[] { - SimpleType.LONG, SimpleType.LONG, - SimpleType.LONG, SimpleType.LONG - }); - ThreadInfo.checkAttribute(type, "usage", uType); - } - catch (OpenDataException e) - { - throw new IllegalStateException("Something went wrong in creating " + - "the composite data type for the " + - "memory usage element.", e); - } + ThreadInfo.checkAttribute(type, "usage", MemoryMXBeanImpl.usageType); ThreadInfo.checkAttribute(type, "count", SimpleType.LONG); MemoryUsage usage = MemoryUsage.from((CompositeData) data.get("usage")); return new MemoryNotificationInfo(((String) data.get("poolName")), diff --git a/java/lang/management/MemoryPoolMXBean.java b/java/lang/management/MemoryPoolMXBean.java index 29b438c29..5b04c64d3 100644 --- a/java/lang/management/MemoryPoolMXBean.java +++ b/java/lang/management/MemoryPoolMXBean.java @@ -157,6 +157,14 @@ public interface MemoryPoolMXBean MemoryUsage getPeakUsage(); /** + * Returns the type of memory used by this pool. This can be + * either heap or non-heap memory. + * + * @return the type of this pool. + */ + String getType(); + + /** * Returns memory usage statistics for the current memory usage * of the pool. The return value may be <code>null</code> if * this pool is no longer valid. Obtaining these values is diff --git a/java/net/Inet6Address.java b/java/net/Inet6Address.java index 0d62fe919..8d834a6fd 100644 --- a/java/net/Inet6Address.java +++ b/java/net/Inet6Address.java @@ -39,13 +39,16 @@ exception statement from your version. */ package java.net; import java.util.Arrays; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; /* * Written using on-line Java Platform 1.4 API Specification and * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt) * * @author Michael Koch - * @status Believed complete and correct. + * @status Updated to 1.5. Serialization compatibility is tested. */ public final class Inet6Address extends InetAddress { @@ -57,6 +60,39 @@ public final class Inet6Address extends InetAddress byte[] ipaddress; /** + * The scope ID, if any. + * @since 1.5 + * @serial + */ + private int scope_id; + + /** + * The scope ID, if any. + * @since 1.5 + * @serial + */ + private boolean scope_id_set; + + /** + * Whether ifname is set or not. + * @since 1.5 + * @serial + */ + private boolean scope_ifname_set; + + /** + * Name of the network interface, used only by the serialization methods + * @since 1.5 + * @serial + */ + private String ifname; + + /** + * Scope network interface, or <code>null</code>. + */ + private transient NetworkInterface nif; + + /** * Create an Inet6Address object * * @param addr The IP address @@ -67,6 +103,10 @@ public final class Inet6Address extends InetAddress super(addr, host); // Super constructor clones the addr. Get a reference to the clone. this.ipaddress = this.addr; + ifname = null; + scope_ifname_set = scope_id_set = false; + scope_id = 0; + nif = null; } /** @@ -199,6 +239,75 @@ public final class Inet6Address extends InetAddress } /** + * Creates a scoped Inet6Address where the scope has an integer id. + * + * @throws UnkownHostException if the address is an invalid number of bytes. + * @since 1.5 + */ + public static Inet6Address getByAddress(String host, byte[] addr, + int scopeId) + throws UnknownHostException + { + if( addr.length != 16 ) + throw new UnknownHostException("Illegal address length: " + addr.length + + " bytes."); + Inet6Address ip = new Inet6Address( addr, host ); + ip.scope_id = scopeId; + ip.scope_id_set = true; + return ip; + } + + /** + * Creates a scoped Inet6Address where the scope is a given + * NetworkInterface. + * + * @throws UnkownHostException if the address is an invalid number of bytes. + * @since 1.5 + */ + public static Inet6Address getByAddress(String host, byte[] addr, + NetworkInterface nif) + throws UnknownHostException + { + if( addr.length != 16 ) + throw new UnknownHostException("Illegal address length: " + addr.length + + " bytes."); + Inet6Address ip = new Inet6Address( addr, host ); + ip.nif = nif; + + return ip; + } + + /** + * Returns the <code>NetworkInterface</code> of the address scope + * if it is a scoped address and the scope is given in the form of a + * NetworkInterface. + * (I.e. the address was created using the + * getByAddress(String, byte[], NetworkInterface) method) + * Otherwise this method returns <code>null</code>. + * @since 1.5 + */ + public NetworkInterface getScopedInterface() + { + return nif; + } + + /** + * Returns the scope ID of the address scope if it is a scoped adress using + * an integer to identify the scope. + * + * Otherwise this method returns 0. + * @since 1.5 + */ + public int getScopeId() + { + // check scope_id_set because some JDK-serialized objects seem to have + // scope_id set to a nonzero value even when scope_id_set == false + if( scope_id_set ) + return scope_id; + return 0; + } + + /** * Returns the IP address string in textual presentation */ public String getHostAddress() @@ -214,12 +323,17 @@ public final class Inet6Address extends InetAddress sbuf.append(Integer.toHexString(x)); } + if( nif != null ) + sbuf.append( "%" + nif.getName() ); + else if( scope_id_set ) + sbuf.append( "%" + scope_id ); return sbuf.toString(); } /** * Returns a hashcode for this IP address + * (The hashcode is independent of scope) */ public int hashCode() { @@ -234,10 +348,23 @@ public final class Inet6Address extends InetAddress if (! (obj instanceof Inet6Address)) return false; - // this.ipaddress is never set in this class except to - // the value of the super class' addr. The super classes - // equals(Object) will do the compare. - return super.equals(obj); + Inet6Address ip = (Inet6Address)obj; + if (ipaddress.length != ip.ipaddress.length) + return false; + + for (int i = 0; i < ip.ipaddress.length; i++) + if (ipaddress[i] != ip.ipaddress[i]) + return false; + + if( ip.nif != null && nif != null ) + return nif.equals( ip.nif ); + if( ip.nif != nif ) + return false; + if( ip.scope_id_set != scope_id_set ) + return false; + if( scope_id_set ) + return (scope_id == ip.scope_id); + return true; } /** @@ -258,4 +385,38 @@ public final class Inet6Address extends InetAddress return true; } + + /** + * Required for 1.5-compatible serialization. + * @since 1.5 + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + try + { + if( scope_ifname_set ) + nif = NetworkInterface.getByName( ifname ); + } + catch( SocketException se ) + { + // FIXME: Ignore this? or throw an IOException? + } + } + + /** + * Required for 1.5-compatible serialization. + * @since 1.5 + */ + private void writeObject(ObjectOutputStream s) + throws IOException + { + if( nif != null ) + { + ifname = nif.getName(); + scope_ifname_set = true; + } + s.defaultWriteObject(); + } } diff --git a/javax/imageio/spi/IIORegistry.java b/javax/imageio/spi/IIORegistry.java index 36618d7f8..fc3087f0c 100644 --- a/javax/imageio/spi/IIORegistry.java +++ b/javax/imageio/spi/IIORegistry.java @@ -48,6 +48,7 @@ import java.util.Iterator; import gnu.javax.imageio.bmp.BMPImageReaderSpi; import gnu.javax.imageio.bmp.BMPImageWriterSpi; import gnu.javax.imageio.gif.GIFImageReaderSpi; +import gnu.javax.imageio.png.PNGImageReaderSpi; public final class IIORegistry extends ServiceRegistry { @@ -84,7 +85,8 @@ public final class IIORegistry extends ServiceRegistry super(defaultCategories.iterator()); // XXX: Register built-in Spis here. - registerServiceProvider(new GIFImageReaderSpi()); // Register GIF decoder + registerServiceProvider(new PNGImageReaderSpi()); // Register PNG decoder. + registerServiceProvider(new GIFImageReaderSpi()); // Register GIF decoder. registerServiceProvider(new BMPImageReaderSpi()); registerServiceProvider(new BMPImageWriterSpi()); diff --git a/javax/management/openmbean/CompositeData.java b/javax/management/openmbean/CompositeData.java index 14b88ff4e..08f0dc253 100644 --- a/javax/management/openmbean/CompositeData.java +++ b/javax/management/openmbean/CompositeData.java @@ -73,9 +73,9 @@ public interface CompositeData /** * Compares the specified object with this object for equality. * The object is judged equivalent if it is non-null, and also - * an instance of {@link CompositeData} with the same values - * and types. The two compared instances may be equivalent even - * if they represent different implementations of + * an instance of {@link CompositeData} with the same name-value + * mappings and types. The two compared instances may be + * equivalent even if they represent different implementations of * {@link CompositeData}. * * @param obj the object to compare for equality. @@ -105,7 +105,7 @@ public interface CompositeData * empty string. * @throws InvalidKeyException if one of the keys does not exist. */ - Object[] getAll(String[] key); + Object[] getAll(String[] keys); /** * Returns the composite type which corresponds to this instance diff --git a/javax/management/openmbean/CompositeDataSupport.java b/javax/management/openmbean/CompositeDataSupport.java new file mode 100644 index 000000000..5d5adb727 --- /dev/null +++ b/javax/management/openmbean/CompositeDataSupport.java @@ -0,0 +1,349 @@ +/* CompositeData.java -- A composite data structure implementation. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.management.openmbean; + +import java.io.Serializable; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * Provides an implementation of the {@link CompositeData} + * interface. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class CompositeDataSupport + implements CompositeData, Serializable +{ + + /** + * Compatible with JDK 1.5 + */ + private static final long serialVersionUID = 8003518976613702244L; + + /** + * Mapping of field names to values. + * + * @serial the map of field names to values. + */ + private SortedMap contents; + + /** + * The composite type which represents this composite data instance. + * + * @serial the type information for this instance. + */ + private CompositeType compositeType; + + /** + * Constructs a new {@link CompositeDataSupport} instance with the + * specified type using field names and values from the supplied map. + * The keys of the map become the field names, while the values + * become the values of each respective field. This constructor simply + * calls the other constructor, with the two arrays formed using the + * keys and values of this map, respectively. Thus, the input parameters + * given should conform to the same requirements given there (i.e. no + * null values or empty strings). + * + * @param type the composite type of this composite data structure. + * @param items a mapping of field names to values. This should match + * the mappings given by the type (i.e. for each mapping + * in the type, there should be a corresponding field name + * with a value of the correct type). + * @throws IllegalArgumentException if the type, the map or any of the keys + * or values in the map are <code>null</code>, + * or if any key from the map is an empty + * string. + * @throws OpenDataException if a mismatch occurs between the map and the + * field name/type specification given by the + * {@link CompositeType} instance. This may be + * due to the two having a different size, a + * mismatch between keys or an incorrectly typed + * value. + * @throws ArrayStoreException if one of the keys is not a + * {@link java.lang.String} (thus calling a failure + * in converting the keys to an array of strings). + */ + public CompositeDataSupport(CompositeType type, Map items) + throws OpenDataException + { + this(type, + (String[]) items.keySet().toArray(new String[items.size()]), + items.values().toArray()); + } + + /** + * Constructs a new {@link CompositeDataSupport} instance with the + * specified type using the supplied arrays of field names and + * values. Neither the type, the two arrays or any elements of the + * arrays may be <code>null</code>. The {@link java.lang.String}s + * within the <code>names</code> array must be non-empty. The + * arrays must match in size and order, as each element of the + * <code>names</code> array is matched against the corresponding + * value in the <code>values</code> array. Internally, the two are + * stored in a map, lexographically ordered using the field names. + * The data given should also conform to the description of the + * instance given by the {@link CompositeType} instance supplied. + * + * @param type the composite type of this composite data structure. + * @param names the field names. + * @param values the corresponding values of the fields. + * @throws IllegalArgumentException if the type, the arrays or any of the keys + * or values in the arrays are <code>null</code>, + * or if any key from <code>names</code> is + * an empty string. This also occurs if the + * arrays differ in length. + * @throws OpenDataException if a mismatch occurs between the arrays and the + * field name/type specification given by the + * {@link CompositeType} instance. This may be + * due to a differing number of field names, a + * mismatch between names or an incorrectly typed + * value. + */ + public CompositeDataSupport(CompositeType type, String[] names, Object[] values) + throws OpenDataException + { + if (type == null) + throw new IllegalArgumentException("The given composite type is null."); + compositeType = type; + if (names == null) + throw new IllegalArgumentException("The names array is null."); + if (values == null) + throw new IllegalArgumentException("The values array is null."); + if (names.length != values.length) + throw new IllegalArgumentException("The sizes of the arrays differ."); + Set typeKeys = type.keySet(); + if (typeKeys.size() != names.length) + throw new OpenDataException("The number of field names does not match " + + "the type description."); + contents = new TreeMap(); + for (int a = 0; a < names.length; ++a) + { + if (names[a] == null) + throw new IllegalArgumentException("Element " + a + " of the names " + + "array is null."); + if (names[a].length() == 0) + throw new IllegalArgumentException("Element " + a + " of the names " + + "array is an empty string."); + if (values[a] == null) + throw new IllegalArgumentException("Element " + a + " of the values " + + "array is null."); + if (!(typeKeys.contains(names[a]))) + throw new OpenDataException("The name, " + names[a] + ", is not a " + + "field in the given type description."); + if (!(type.getType(names[a]).isValue(values[a]))) + throw new OpenDataException("The value, " + values[a] + ", is not a " + + "valid value for the " + names[a] + " field."); + contents.put(names[a], values[a]); + } + } + + /** + * Returns true if this {@link CompositeData} instance contains + * the specified key. This method always returns false for + * an input key equal to <code>null</code> or the empty string. + * + * @param key the key to find in the structure. + * @return true if the key exists. + */ + public boolean containsKey(String key) + { + if (key == null || key.length() == 0) + return false; + else + return contents.containsKey(key); + } + + /** + * Returns true if this {@link CompositeData} instance has + * a value equal to that supplied. + * + * @param value the value to look for. + * @return true if the value exists. + */ + public boolean containsValue(Object value) + { + return contents.containsValue(value); + } + + + /** + * Compares the specified object with this object for equality. + * The object is judged equivalent if it is non-null, and also + * an instance of {@link CompositeData} with the same name-value + * mappings and types. The two compared instances may be + * equivalent even if they represent different implementations of + * {@link CompositeData}. + * + * @param obj the object to compare for equality. + * @return true if <code>obj</code> is equal to <code>this</code>. + */ + public boolean equals(Object obj) + { + if (!(obj instanceof CompositeData)) + return false; + CompositeData data = (CompositeData) obj; + if (!(data.getCompositeType().equals(compositeType))) + return false; + Iterator it = contents.keySet().iterator(); + while (it.hasNext()) + { + String key = (String) it.next(); + if (!(data.containsKey(key))) + return false; + if (!(data.get(key).equals(contents.get(key)))) + return false; + } + return true; + } + + /** + * Retrieves the value for the specified key. + * + * @param key the key whose value should be returned. + * @return the matching value. + * @throws IllegalArgumentException if the key is <code>null</code> + * or the empty string. + * @throws InvalidKeyException if the key does not exist. + */ + public Object get(String key) + { + if (key == null) + throw new IllegalArgumentException("The supplied key is null."); + if (key.length() == 0) + throw new IllegalArgumentException("The supplied key is the empty string."); + if (!(contents.containsKey(key))) + throw new InvalidKeyException("The supplied key does not exist."); + return contents.get(key); + } + + /** + * Returns the appropriate value for each key in the given array, + * using the same ordering. + * + * @param keys the keys whose values should be returned. + * @return the matching values. + * @throws IllegalArgumentException if one of the keys is + * <code>null</code> or the + * empty string. + * @throws InvalidKeyException if one of the keys does not exist. + */ + public Object[] getAll(String[] keys) + { + Object[] values = new Object[keys.length]; + for (int a = 0; a < keys.length; ++a) + values[a] = get(keys[a]); + return values; + } + + + /** + * Returns the composite type which corresponds to this instance + * of {@link CompositeData}. + * + * @return the composite type for this instance. + */ + public CompositeType getCompositeType() + { + return compositeType; + } + + /** + * Returns the hash code of this instance. The hash code is + * computed as the sum of the hash codes of all the values plus + * the hash code of the composite type. As equality comparisons + * take place using this same information, this should ensure that + * the property, <code>e1.equals(e2)</code> implies + * <code>e1.hashCode() == e2.hashCode(), holds for any pair + * of instances, <code>e1</code> and <code>e2</code>. However, + * this relies on the other instance implementing the + * <code>hashCode</code> method correctly, if it is not an + * instance of {@link CompositeDataSupport}. + * + * @return the hash code of this {@link CompositeData}. + * @see Object#equals(Object) + */ + public int hashCode() + { + int code = compositeType.hashCode(); + Iterator it = values().iterator(); + while (it.hasNext()) + code += it.next().hashCode(); + return code; + } + + + /** + * Returns a textual representation of this instance. The + * exact format is left up to the implementation, but it + * should contain the name of the implementing class, + * the name of the type and a mapping of the form + * <code>key=value</code> for each pair of key and value. + * + * @return a {@link java.lang.String} representation of the + * object. + */ + public String toString() + { + return getClass().getName() + + "[compositeType=" + compositeType + + ",contents=" + contents + + "]"; + } + + /** + * Returns a read-only collection of the values associated with + * this instance. The values are sorted using the lexicographic + * ordering of the corresponding keys. + * + * @return the values of this instance. + */ + public Collection values() + { + return Collections.unmodifiableCollection(contents.values()); + } + +} + diff --git a/javax/management/openmbean/InvalidKeyException.java b/javax/management/openmbean/InvalidKeyException.java new file mode 100644 index 000000000..5f0cf7603 --- /dev/null +++ b/javax/management/openmbean/InvalidKeyException.java @@ -0,0 +1,77 @@ +/* InvalidKeyException.java -- Thrown by an invalid composite/tabular key. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.management.openmbean; + +/** + * Thrown when an invalid key (a field name or row index) is + * passed to a method of the {@link CompositeData} or + * {@link TabularData} classes. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class InvalidKeyException + extends IllegalArgumentException +{ + + /** + * Compatible with JDK 1.5 + */ + private static final long serialVersionUID = 4224269443946322062L; + + /** + * Constructs a new <code>InvalidKeyException</code>. + */ + public InvalidKeyException() + { + super(); + } + + /** + * Constructs a new <code>InvalidKeyException</code> + * with the specified message. + * + * @param message the error message to give to the user. + */ + public InvalidKeyException(String message) + { + super(message); + } + +} + diff --git a/javax/security/auth/login/LoginContext.java b/javax/security/auth/login/LoginContext.java index 740e67b8b..17641e65b 100644 --- a/javax/security/auth/login/LoginContext.java +++ b/javax/security/auth/login/LoginContext.java @@ -1,5 +1,5 @@ /* LoginContext.java - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -91,6 +91,9 @@ public class LoginContext Configuration config) throws LoginException { + this.name = name; + this.subject = subject; + this.cbHandler = cbHandler; if (config == null) config = Configuration.getConfig(); AppConfigurationEntry[] entries = config.getAppConfigurationEntry (name); @@ -104,9 +107,6 @@ public class LoginContext sharedState = new HashMap(); for (int i = 0; i < entries.length; i++) modules[i] = lookupModule (entries[i], subject, sharedState); - this.name = name; - this.subject = subject; - this.cbHandler = cbHandler; } /** diff --git a/javax/swing/JComponent.java b/javax/swing/JComponent.java index 1ab80f691..d35fde7a9 100644 --- a/javax/swing/JComponent.java +++ b/javax/swing/JComponent.java @@ -48,12 +48,10 @@ import java.awt.EventQueue; import java.awt.FocusTraversalPolicy; import java.awt.Font; import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.Image; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; -import java.awt.Shape; import java.awt.Window; import java.awt.dnd.DropTarget; import java.awt.event.ActionEvent; @@ -71,7 +69,6 @@ import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import java.beans.VetoableChangeSupport; import java.io.Serializable; -import java.util.ArrayList; import java.util.EventListener; import java.util.Hashtable; import java.util.Locale; @@ -1940,227 +1937,77 @@ public abstract class JComponent extends Container implements Serializable { if (getComponentCount() > 0) { - if (isOptimizedDrawingEnabled()) - paintChildrenOptimized(g); - else - paintChildrenWithOverlap(g); - } - } - - /** - * Paints the children of this JComponent in the case when the component - * is not marked as optimizedDrawingEnabled, that means the container cannot - * guarantee that it's children are tiled. For this case we must - * perform a more complex optimization to determine the minimal rectangle - * to be painted for each child component. - * - * @param g the graphics context to use - */ - private void paintChildrenWithOverlap(Graphics g) - { - Shape originalClip = g.getClip(); - Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache); - g.clipRect(inner.x, inner.y, inner.width, inner.height); - - // Find the rectangles that need to be painted for each child component. - // We push on this list arrays that have the Rectangles to be painted as - // the first elements and the component to be painted as the last one. - // Later we go through that list in reverse order and paint the rectangles. - int numChildren = getComponentCount(); - ArrayList paintRegions = new ArrayList(numChildren); - ArrayList paintRectangles = new ArrayList(); - ArrayList newPaintRects = new ArrayList(); - paintRectangles.add(g.getClipBounds()); - ArrayList componentRectangles = new ArrayList(); - - // Go through children from top to bottom and find out their paint - // rectangles. - for (int index = 0; paintRectangles.size() > 0 && index < numChildren; index++) - { - Component comp = getComponent(index); - if (! comp.isVisible() || ! comp.isLightweight()) - continue; - - Rectangle compBounds = comp.getBounds(); - boolean isOpaque = comp.isOpaque(); - - // Add all the current paint rectangles that intersect with the - // component to the component's paint rectangle array. - for (int i = paintRectangles.size() - 1; i >= 0; i--) + // Need to lock the tree to avoid problems with AWT and concurrency. + synchronized (getTreeLock()) { - Rectangle r = (Rectangle) paintRectangles.get(i); - if (r.intersects(compBounds)) + for (int i = getComponentCount() - 1; i >= 0; i--) { - Rectangle compRect = r.intersection(compBounds); - componentRectangles.add(compRect); - // If the component is opaque, split up each paint rect and - // add paintRect - compBounds to the newPaintRects array. - if (isOpaque) + Component child = getComponent(i); + if (child != null && child.isLightweight() + && child.isVisible()) { - int x, y, w, h; - Rectangle rect = new Rectangle(); - - // The north rectangle. - x = Math.max(compBounds.x, r.x); - y = r.y; - w = Math.min(compBounds.width, r.width + r.x - x); - h = compBounds.y - r.y; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) - { - newPaintRects.add(rect); - rect = new Rectangle(); - } - - // The south rectangle. - x = Math.max(compBounds.x, r.x); - y = compBounds.y + compBounds.height; - w = Math.min(compBounds.width, r.width + r.x - x); - h = r.height - (compBounds.y - r.y) - compBounds.height; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) - { - newPaintRects.add(rect); - rect = new Rectangle(); - } - - // The west rectangle. - x = r.x; - y = r.y; - w = compBounds.x - r.x; - h = r.height; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) + int cx = child.getX(); + int cy = child.getY(); + int cw = child.getWidth(); + int ch = child.getHeight(); + if (g.hitClip(cx, cy, cw, ch)) { - newPaintRects.add(rect); - rect = new Rectangle(); + if ((! isOptimizedDrawingEnabled()) && i > 0) + { + // Check if the child is completely obscured. + Rectangle clip = g.getClipBounds(); // A copy. + SwingUtilities.computeIntersection(cx, cy, cw, ch, + clip); + if (isCompletelyObscured(i, clip)) + continue; // Continues the for-loop. + } + Graphics cg = g.create(cx, cy, cw, ch); + cg.setColor(child.getForeground()); + cg.setFont(child.getFont()); + try + { + child.paint(cg); + } + finally + { + cg.dispose(); + } } - - // The east rectangle. - x = compBounds.x + compBounds.width; - y = r.y; - w = r.width - (compBounds.x - r.x) - compBounds.width; - h = r.height; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) - { - newPaintRects.add(rect); - } - } - else - { - // Not opaque, need to reuse the current paint rectangles - // for the next component. - newPaintRects.add(r); } - - } - else - { - newPaintRects.add(r); } } - - // Replace the paintRectangles with the new split up - // paintRectangles. - paintRectangles.clear(); - paintRectangles.addAll(newPaintRects); - newPaintRects.clear(); - - // Store paint rectangles if there are any for the current component. - int compRectsSize = componentRectangles.size(); - if (compRectsSize > 0) - { - componentRectangles.add(comp); - paintRegions.add(componentRectangles); - componentRectangles = new ArrayList(); - } } - - // paintingTile becomes true just before we start painting the component's - // children. - paintingTile = true; - - // We must go through the painting regions backwards, because the - // topmost components have been added first, followed by the components - // below. - int prEndIndex = paintRegions.size() - 1; - for (int i = prEndIndex; i >= 0; i--) - { - // paintingTile must be set to false before we begin to start painting - // the last tile. - if (i == 0) - paintingTile = false; - - ArrayList paintingRects = (ArrayList) paintRegions.get(i); - // The last element is always the component. - Component c = (Component) paintingRects.get(paintingRects.size() - 1); - int endIndex = paintingRects.size() - 2; - for (int j = 0; j <= endIndex; j++) - { - Rectangle cBounds = c.getBounds(); - Rectangle bounds = (Rectangle) paintingRects.get(j); - Rectangle oldClip = g.getClipBounds(); - if (oldClip == null) - oldClip = bounds; - - boolean translated = false; - try - { - g.setClip(bounds); - g.translate(cBounds.x, cBounds.y); - translated = true; - c.paint(g); - } - finally - { - if (translated) - g.translate(-cBounds.x, -cBounds.y); - g.setClip(oldClip); - } - } - } - g.setClip(originalClip); } /** - * Paints the children of this container when it is marked as - * optimizedDrawingEnabled. In this case the container can guarantee that - * it's children are tiled, which allows for a much more efficient - * algorithm to determine the minimum rectangles to be painted for - * each child. + * Determines if a region of a child component is completely obscured by one + * of its siblings. + * + * @param index the index of the child component + * @param rect the region to check * - * @param g the graphics context to use + * @return <code>true</code> if the region is completely obscured by a + * sibling, <code>false</code> otherwise */ - private void paintChildrenOptimized(Graphics g) + private boolean isCompletelyObscured(int index, Rectangle rect) { - Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache); - g.clipRect(inner.x, inner.y, inner.width, inner.height); - - // paintingTile becomes true just before we start painting the component's - // children. - paintingTile = true; - int numChildren = getComponentCount(); - for (int i = numChildren - 1; i >= 0; i--) //children.length; i++) + boolean obscured = false; + for (int i = index - 1; i >= 0 && obscured == false; i--) { - Component child = getComponent(i); - // paintingTile must be set to false before we begin to start painting - // the last tile. - if (i == numChildren - 1) - paintingTile = false; - - if (!child.isVisible() || ! child.isLightweight()) - continue; - - Rectangle bounds = child.getBounds(rectCache); - if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height)) - continue; - - Graphics g2 = g.create(bounds.x, bounds.y, bounds.width, - bounds.height); - child.paint(g2); - g2.dispose(); + Component sib = getComponent(i); + if (sib.isVisible()) + { + Rectangle sibRect = sib.getBounds(rectCache); + if (sib.isOpaque() && rect.x >= sibRect.x + && (rect.x + rect.width) <= (sibRect.x + sibRect.width) + && rect.y >= sibRect.y + && (rect.y + rect.height) <= (sibRect.y + sibRect.height)) + { + obscured = true; + } + } } + return obscured; } /** @@ -2180,12 +2027,15 @@ public abstract class JComponent extends Container implements Serializable { if (ui != null) { - Graphics g2 = g; - if (!(g instanceof Graphics2D)) - g2 = g.create(); - ui.update(g2, this); - if (!(g instanceof Graphics2D)) - g2.dispose(); + Graphics g2 = g.create(); + try + { + ui.update(g2, this); + } + finally + { + g2.dispose(); + } } } @@ -2329,11 +2179,16 @@ public abstract class JComponent extends Container implements Serializable private void clipAndTranslateGraphics(Component root, Component target, Graphics g) { - Component parent = target.getParent(); - if (parent != root) - clipAndTranslateGraphics(root, parent, g); - - g.translate(target.getX(), target.getY()); + Component parent = target; + int deltaX = 0; + int deltaY = 0; + while (parent != root) + { + deltaX += parent.getX(); + deltaY += parent.getY(); + parent = parent.getParent(); + } + g.translate(deltaX, deltaY); g.clipRect(0, 0, target.getWidth(), target.getHeight()); } diff --git a/javax/swing/JTable.java b/javax/swing/JTable.java index 026d1b899..b8946213b 100644 --- a/javax/swing/JTable.java +++ b/javax/swing/JTable.java @@ -2922,56 +2922,190 @@ public class JTable { // update the column model from the table model if the structure has // changed and the flag autoCreateColumnsFromModel is set - if ((event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW)) - && autoCreateColumnsFromModel) + if (event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW)) + handleCompleteChange(event); + else if (event.getType() == TableModelEvent.INSERT) + handleInsert(event); + else if (event.getType() == TableModelEvent.DELETE) + handleDelete(event); + else + handleUpdate(event); + } + + /** + * Handles a request for complete relayout. This is the case when + * event.getFirstRow() == TableModelEvent.HEADER_ROW. + * + * @param ev the table model event + */ + private void handleCompleteChange(TableModelEvent ev) + { + clearSelection(); + checkSelection(); + rowHeights = null; + if (getAutoCreateColumnsFromModel()) + createDefaultColumnsFromModel(); + else + resizeAndRepaint(); + } + + /** + * Handles table model insertions. + * + * @param ev the table model event + */ + private void handleInsert(TableModelEvent ev) + { + // Sync selection model with data model. + int first = ev.getFirstRow(); + if (first < 0) + first = 0; + int last = ev.getLastRow(); + if (last < 0) + last = getRowCount() - 1; + selectionModel.insertIndexInterval(first, last - first + 1, true); + checkSelection(); + + // For variable height rows we must update the SizeSequence thing. + if (rowHeights != null) { - rowHeights = null; - if (getAutoCreateColumnsFromModel()) - createDefaultColumnsFromModel(); - resizeAndRepaint(); - return; + rowHeights.insertEntries(first, last - first + 1, rowHeight); + // Repaint the dirty region and revalidate. + int rowHeight = getRowHeight(); + Rectangle dirty = new Rectangle(0, first * rowHeight, + getColumnModel().getTotalColumnWidth(), + (getRowCount() - first) * rowHeight); + repaint(dirty); + } + else + { + // TODO: We repaint the whole thing when the rows have variable + // heights. We might want to handle this better though. + repaint(); + } + revalidate(); + } + + /** + * Handles table model deletions. + * + * @param ev the table model event + */ + private void handleDelete(TableModelEvent ev) + { + // Sync selection model with data model. + int first = ev.getFirstRow(); + if (first < 0) + first = 0; + int last = ev.getLastRow(); + if (last < 0) + last = getRowCount() - 1; + + selectionModel.removeIndexInterval(first, last); + + checkSelection(); + + if (dataModel.getRowCount() == 0) + clearSelection(); + + // For variable height rows we must update the SizeSequence thing. + if (rowHeights != null) + { + rowHeights.removeEntries(first, last - first + 1); + + // Repaint the dirty region and revalidate. + int rowHeight = getRowHeight(); + int oldRowCount = getRowCount() + last - first + 1; + Rectangle dirty = new Rectangle(0, first * rowHeight, + getColumnModel().getTotalColumnWidth(), + (oldRowCount - first) * rowHeight); + repaint(dirty); + } + else + { + // TODO: We repaint the whole thing when the rows have variable + // heights. We might want to handle this better though. + repaint(); } + revalidate(); + } - // If the structure changes, we need to revalidate, since that might - // affect the size parameters of the JTable. Otherwise we only need - // to perform a repaint to update the view. - if (event == null || event.getType() == TableModelEvent.INSERT) + /** + * Handles table model updates without structural changes. + * + * @param ev the table model event + */ + private void handleUpdate(TableModelEvent ev) + { + if (rowHeights != null) { - // Sync selection model with data model. - if (event != null) + // Some cells have been changed without changing the structure. + // Figure out the dirty rectangle and repaint. + int firstRow = ev.getFirstRow(); + int lastRow = ev.getLastRow(); + int col = ev.getColumn(); + Rectangle dirty; + if (col == TableModelEvent.ALL_COLUMNS) { - int first = event.getFirstRow(); - if (first < 0) - first = 0; - int last = event.getLastRow(); - if (last < 0) - last = getRowCount() - 1; - selectionModel.insertIndexInterval(first, last - first + 1, true); - if (rowHeights != null) - rowHeights.insertEntries(first, last - first + 1, rowHeight); + // All columns changed. + dirty = new Rectangle(0, firstRow * getRowHeight(), + getColumnModel().getTotalColumnWidth(), 0); } - revalidate(); + else + { + // Only one cell or column of cells changed. + // We need to convert to view column first. + int column = convertColumnIndexToModel(col); + dirty = getCellRect(firstRow, column, false); + } + + // Now adjust the height of the dirty region. + dirty.height = (lastRow + 1) * getRowHeight(); + // .. and repaint. + repaint(dirty); } - if (event == null || event.getType() == TableModelEvent.DELETE) + else { - // Sync selection model with data model. - if (event != null) + // TODO: We repaint the whole thing when the rows have variable + // heights. We might want to handle this better though. + repaint(); + } + } + + /** + * Helper method for adjusting the lead and anchor indices when the + * table structure changed. This sets the lead and anchor to -1 if there's + * no more rows, or set them to 0 when they were at -1 and there are actually + * some rows now. + */ + private void checkSelection() + { + TableModel m = getModel(); + ListSelectionModel sm = selectionModel; + if (m != null) + { + int lead = sm.getLeadSelectionIndex(); + int c = m.getRowCount(); + if (c == 0 && lead != -1) + { + // No rows in the model, reset lead and anchor to -1. + sm.setValueIsAdjusting(true); + sm.setAnchorSelectionIndex(-1); + sm.setLeadSelectionIndex(-1); + sm.setValueIsAdjusting(false); + } + else if (c != 0 && lead == -1) { - int first = event.getFirstRow(); - if (first < 0) - first = 0; - int last = event.getLastRow(); - if (last < 0) - last = getRowCount() - 1; - selectionModel.removeIndexInterval(first, last); - if (rowHeights != null) - rowHeights.removeEntries(first, last - first + 1); + // We have rows, but no lead/anchor. Set them to 0. We + // do a little trick here so that the actual selection is not + // touched. + if (sm.isSelectedIndex(0)) + sm.addSelectionInterval(0, 0); + else + sm.removeSelectionInterval(0, 0); } - if (dataModel.getRowCount() == 0) - clearSelection(); - revalidate(); + // Nothing to do in the other cases. } - repaint(); } /** @@ -4030,6 +4164,7 @@ public class JTable if (s != null) s.addListSelectionListener(this); selectionModel = s; + checkSelection(); } /** diff --git a/javax/swing/RepaintManager.java b/javax/swing/RepaintManager.java index 262054319..6e0772d56 100644 --- a/javax/swing/RepaintManager.java +++ b/javax/swing/RepaintManager.java @@ -38,7 +38,6 @@ exception statement from your version. */ package javax.swing; -import java.applet.Applet; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; @@ -647,7 +646,7 @@ public class RepaintManager width = Math.min(doubleBufferMaximumSize.width, width); int height = Math.max(proposedHeight, root.getHeight()); height = Math.min(doubleBufferMaximumSize.height, height); - buffer = component.createImage(width, height); + buffer = root.createImage(width, height); offscreenBuffers.put(root, buffer); } return buffer; diff --git a/javax/swing/plaf/basic/BasicButtonListener.java b/javax/swing/plaf/basic/BasicButtonListener.java index fe0365a50..3b4759ae4 100644 --- a/javax/swing/plaf/basic/BasicButtonListener.java +++ b/javax/swing/plaf/basic/BasicButtonListener.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.SystemProperties; + import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; @@ -71,8 +73,10 @@ public class BasicButtonListener implements MouseListener, MouseMotionListener, // Store the TextLayout for this in a client property for speed-up // painting of the label. String property = e.getPropertyName(); - if (property.equals(AbstractButton.TEXT_CHANGED_PROPERTY) - || property.equals("font")) + if ((property.equals(AbstractButton.TEXT_CHANGED_PROPERTY) + || property.equals("font")) + && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") + == null) { AbstractButton b = (AbstractButton) e.getSource(); String text = b.getText(); diff --git a/javax/swing/plaf/basic/BasicMenuItemUI.java b/javax/swing/plaf/basic/BasicMenuItemUI.java index c5ed2ff7e..bbc08535c 100644 --- a/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.SystemProperties; + import java.awt.Color; import java.awt.Component; import java.awt.Container; @@ -256,8 +258,11 @@ public class BasicMenuItemUI extends MenuItemUI map.put(accelerator, "doClick"); } // TextLayout caching for speed-up drawing of text. - else if (property.equals(AbstractButton.TEXT_CHANGED_PROPERTY) - || property.equals("font")) + else if ((property.equals(AbstractButton.TEXT_CHANGED_PROPERTY) + || property.equals("font")) + && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") + == null) + { AbstractButton b = (AbstractButton) e.getSource(); String text = b.getText(); diff --git a/javax/swing/plaf/metal/MetalLookAndFeel.java b/javax/swing/plaf/metal/MetalLookAndFeel.java index b496a2b0e..da16159c9 100644 --- a/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -1185,20 +1185,26 @@ public class MetalLookAndFeel extends BasicLookAndFeel "SplitPaneDivider.draggingColor", Color.DARK_GRAY, "TabbedPane.background", getControlShadow(), + "TabbedPane.contentBorderInsets", new InsetsUIResource(2, 2, 3, 3), + "TabbedPane.contentOpaque", Boolean.TRUE, "TabbedPane.darkShadow", getControlDarkShadow(), "TabbedPane.focus", getPrimaryControlDarkShadow(), "TabbedPane.font", new FontUIResource("Dialog", Font.BOLD, 12), "TabbedPane.foreground", getControlTextColor(), "TabbedPane.highlight", getControlHighlight(), "TabbedPane.light", getControl(), - "TabbedPane.selected", getControl(), + "TabbedPane.selected", getControl(), // overridden in OceanTheme "TabbedPane.selectHighlight", getControlHighlight(), "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1), "TabbedPane.shadow", getControlShadow(), - "TabbedPane.tabAreaBackground", getControl(), - "TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6), + "TabbedPane.tabAreaBackground", getControl(), // overridden in OceanTheme + "TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6), // dito "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9), + // new properties in OceanTheme: + // TabbedPane.contentAreaColor + // TabbedPane.unselectedBackground + "Table.background", getWindowBackground(), "Table.focusCellBackground", getWindowBackground(), "Table.focusCellForeground", getControlTextColor(), diff --git a/javax/swing/text/html/HTMLEditorKit.java b/javax/swing/text/html/HTMLEditorKit.java index 138a42fbc..b852d568c 100644 --- a/javax/swing/text/html/HTMLEditorKit.java +++ b/javax/swing/text/html/HTMLEditorKit.java @@ -40,8 +40,6 @@ package javax.swing.text.html; import gnu.classpath.NotImplementedException; -import gnu.javax.swing.text.html.parser.GnuParserDelegator; -import gnu.javax.swing.text.html.parser.HTML_401Swing; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; @@ -73,6 +71,11 @@ import javax.swing.text.View; import javax.swing.text.ViewFactory; import javax.swing.text.html.parser.ParserDelegator; +/* Move these imports here after javax.swing.text.html to make it compile + with jikes. */ +import gnu.javax.swing.text.html.parser.GnuParserDelegator; +import gnu.javax.swing.text.html.parser.HTML_401Swing; + /** * @author Lillian Angel (langel at redhat dot com) */ diff --git a/lib/.cvsignore b/lib/.cvsignore index 8ac5f9ba6..93f21e77a 100644 --- a/lib/.cvsignore +++ b/lib/.cvsignore @@ -35,3 +35,4 @@ Makefile.deps lists copy-vmresources.sh classes.2 +standard.omit diff --git a/lib/Makefile.am b/lib/Makefile.am index f0e962346..3192372d9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -44,9 +44,9 @@ COLLECTIONS = collections.jar collections.jar: mkcollections.pl ./mkcollections.pl $(top_srcdir) #if FOUND_GCJ -# $(GCJ) -C `$(FIND) $(COLLECTIONS_PREFIX) -name '*' -type f -print` +# $(GCJ) -C `$(FIND) $(COLLECTIONS_PREFIX) -name '*.java' -type f -print` #else - $(JAVAC) `$(FIND) $(COLLECTIONS_PREFIX) -name '*' -type f -print` + $(JAVAC) `$(FIND) $(COLLECTIONS_PREFIX) -name '*.java' -type f -print` #endif if test "$(FASTJAR)" != ""; then \ $(FASTJAR) cf $@ $(COLLECTIONS_PREFIX); \ diff --git a/lib/mkcollections.pl.in b/lib/mkcollections.pl.in index bd00f01f2..3d2d3c78a 100755 --- a/lib/mkcollections.pl.in +++ b/lib/mkcollections.pl.in @@ -25,7 +25,8 @@ my $destpath=@COLLECTIONS_PREFIX@; my $classpath=pop; my @javalangclasses=qw(UnsupportedOperationException - Comparable); + Comparable + Iterable); my @javautilclasses=qw(AbstractCollection AbstractList AbstractMap diff --git a/native/jni/gtk-peer/GtkDragSourceContextPeer.c b/native/jni/gtk-peer/GtkDragSourceContextPeer.c new file mode 100644 index 000000000..6dfbfcce4 --- /dev/null +++ b/native/jni/gtk-peer/GtkDragSourceContextPeer.c @@ -0,0 +1,256 @@ +/* gtkdragsourcecontextpeer.c -- Native implementation of GtkDragSourceContextPeer + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "gtkpeer.h" +#include "GtkDragSourceContextPeer.h" + +#include <jni.h> +#include <gtk/gtk.h> + +static GtkWidget * get_widget (GtkWidget *widget); + +#define ACTION_COPY 1 +#define ACTION_MOVE 2 +#define ACTION_COPY_OR_MOVE 3 +#define ACTION_LINK 1073741824 + +#define AWT_DEFAULT_CURSOR 0 +#define AWT_CROSSHAIR_CURSOR 1 +#define AWT_TEXT_CURSOR 2 +#define AWT_WAIT_CURSOR 3 +#define AWT_SW_RESIZE_CURSOR 4 +#define AWT_SE_RESIZE_CURSOR 5 +#define AWT_NW_RESIZE_CURSOR 6 +#define AWT_NE_RESIZE_CURSOR 7 +#define AWT_N_RESIZE_CURSOR 8 +#define AWT_S_RESIZE_CURSOR 9 +#define AWT_W_RESIZE_CURSOR 10 +#define AWT_E_RESIZE_CURSOR 11 +#define AWT_HAND_CURSOR 12 +#define AWT_MOVE_CURSOR 13 + +GtkWidget *widget; + +JNIEXPORT void JNICALL +Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create + (JNIEnv *env, jobject obj, jobject comp) +{ + void *ptr; + + gdk_threads_enter (); + + NSA_SET_GLOBAL_REF (env, obj); + NSA_SET_GLOBAL_REF (env, comp); + + ptr = NSA_GET_PTR (env, comp); + widget = get_widget (GTK_WIDGET (ptr)); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeSetCursor + (JNIEnv *env, jobject obj, jint type) +{ + void *ptr; + GdkWindow *win; + GdkCursorType gdk_cursor_type; + GdkCursor *gdk_cursor; + + gdk_threads_enter (); + + ptr = NSA_GET_GLOBAL_REF (env, obj); + + switch (type) + { + case AWT_CROSSHAIR_CURSOR: + gdk_cursor_type = GDK_CROSSHAIR; + break; + case AWT_TEXT_CURSOR: + gdk_cursor_type = GDK_XTERM; + break; + case AWT_WAIT_CURSOR: + gdk_cursor_type = GDK_WATCH; + break; + case AWT_SW_RESIZE_CURSOR: + gdk_cursor_type = GDK_BOTTOM_LEFT_CORNER; + break; + case AWT_SE_RESIZE_CURSOR: + gdk_cursor_type = GDK_BOTTOM_RIGHT_CORNER; + break; + case AWT_NW_RESIZE_CURSOR: + gdk_cursor_type = GDK_TOP_LEFT_CORNER; + break; + case AWT_NE_RESIZE_CURSOR: + gdk_cursor_type = GDK_TOP_RIGHT_CORNER; + break; + case AWT_N_RESIZE_CURSOR: + gdk_cursor_type = GDK_TOP_SIDE; + break; + case AWT_S_RESIZE_CURSOR: + gdk_cursor_type = GDK_BOTTOM_SIDE; + break; + case AWT_W_RESIZE_CURSOR: + gdk_cursor_type = GDK_LEFT_SIDE; + break; + case AWT_E_RESIZE_CURSOR: + gdk_cursor_type = GDK_RIGHT_SIDE; + break; + case AWT_HAND_CURSOR: + gdk_cursor_type = GDK_HAND2; + break; + case AWT_MOVE_CURSOR: + gdk_cursor_type = GDK_FLEUR; + break; + default: + gdk_cursor_type = GDK_LEFT_PTR; + } + + win = widget->window; + if ((widget->window) == NULL) + win = widget->window; + + gdk_cursor = gdk_cursor_new (gdk_cursor_type); + + gdk_window_set_cursor (win, gdk_cursor); + gdk_cursor_unref (gdk_cursor); + + gdk_flush(); + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_connectSignals + (JNIEnv *env, jobject obj, jobject comp) +{ + jobject *gref; + void *ptr; + + gdk_threads_enter (); + + ptr = NSA_GET_GLOBAL_REF (env, obj); + gref = NSA_GET_GLOBAL_REF (env, comp); + + /* Uncomment when needed: + g_signal_connect (G_OBJECT (widget), "drag_motion", + G_CALLBACK (drag_motion_cb), *gref); + g_signal_connect (G_OBJECT (widget), "drag_begin", + G_CALLBACK (drag_begin_cb), *gref); + g_signal_connect (G_OBJECT (widget), "drag_end", + G_CALLBACK (drag_end_cb), *gref); + g_signal_connect (G_OBJECT (widget), "drag_data_get", + G_CALLBACK (drag_data_get_cb), *gref); + g_signal_connect (G_OBJECT (widget), "drag_drop", + G_CALLBACK (drag_drop_cb), *gref); + g_signal_connect (G_OBJECT (widget), "drag_data_delete", + G_CALLBACK (drag_data_delete_cb), *gref); + g_signal_connect (G_OBJECT (widget), "drag_data_received", + G_CALLBACK (drag_data_received_cb), *gref); + */ + + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeStartDrag + (JNIEnv *env, jobject obj, jobject img, jint x, jint y, jint act, + jstring target) +{ + void *ptr; + const gchar *data; + GtkTargetEntry tar[1]; + GdkEvent *event; + GdkPixbuf *image = NULL; + GdkDragContext *context = NULL; + GdkDragAction action = GDK_ACTION_DEFAULT; + + gdk_threads_enter (); + + ptr = NSA_GET_GLOBAL_REF (env, obj); + + data = (*env)->GetStringUTFChars (env, target, NULL); + tar[0].target = (gchar *) data; + event = gdk_event_new (GDK_ALL_EVENTS_MASK); + + switch (act) + { + case ACTION_COPY: + action = GDK_ACTION_COPY; + break; + case ACTION_MOVE: + action = GDK_ACTION_MOVE; + break; + case ACTION_COPY_OR_MOVE: + action = GDK_ACTION_COPY | GDK_ACTION_MOVE; + break; + case ACTION_LINK: + action = GDK_ACTION_LINK; + break; + default: + action = GDK_ACTION_DEFAULT; + } + + gtk_drag_highlight (widget); + context = gtk_drag_begin (widget, + gtk_target_list_new (tar, sizeof (tar) / sizeof (GtkTargetEntry)), + action, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, event); + + if (img != NULL) + { + image = cp_gtk_image_get_pixbuf (env, img); + gtk_drag_set_icon_pixbuf (context, image, x, y); + } + + gdk_event_free (event); + (*env)->ReleaseStringUTFChars (env, target, data); + + gdk_threads_leave (); +} + +static GtkWidget * +get_widget (GtkWidget *widget) +{ + GtkWidget *w; + + if (GTK_IS_EVENT_BOX (widget) || GTK_IS_CONTAINER (widget)) + w = gtk_bin_get_child (GTK_BIN(widget)); + else + w = widget; + + return w; +} diff --git a/native/jni/gtk-peer/Makefile.am b/native/jni/gtk-peer/Makefile.am index 1e0c97156..2af0164b0 100644 --- a/native/jni/gtk-peer/Makefile.am +++ b/native/jni/gtk-peer/Makefile.am @@ -40,6 +40,7 @@ libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \ gnu_java_awt_peer_gtk_GtkToolkit.c \ gnu_java_awt_peer_gtk_GtkWindowPeer.c \ gnu_java_awt_peer_gtk_GtkVolatileImage.c \ + GtkDragSourceContextPeer.c \ cairographics2d.h \ gthread-jni.c \ gdkdisplay.h \ diff --git a/resource/META-INF/services/.cvsignore b/resource/META-INF/services/.cvsignore new file mode 100644 index 000000000..00abb1c13 --- /dev/null +++ b/resource/META-INF/services/.cvsignore @@ -0,0 +1 @@ +java.util.prefs.PreferencesFactory diff --git a/resource/gnu/classpath/tools/jarsigner/messages.properties b/resource/gnu/classpath/tools/jarsigner/messages.properties index 4383256de..d4088177c 100644 --- a/resource/gnu/classpath/tools/jarsigner/messages.properties +++ b/resource/gnu/classpath/tools/jarsigner/messages.properties @@ -119,4 +119,8 @@ SFHelper.1=Helper is NOT finished SFHelper.4=.SF file has NOT been generated SFHelper.6=Unknown or unsupported private key algorithm SFHelper.9=Helper is NOT ready +SFHelper.0=Warning: The certificate issued by {0}, for {1}, has expired as of {3,date,full} - {3,time,full}. SFHelper.10=Helper is NOT started +SFHelper.11=Warning: The certificate issued by {0}, for {1}, is only valid after {3,date,full} - {3,time,full}. +SFHelper.14=[unknown] +SFHelper.17=[unnamed] diff --git a/resource/gnu/java/awt/peer/x/fonts.properties b/resource/gnu/java/awt/peer/x/fonts.properties new file mode 100644 index 000000000..71a95c193 --- /dev/null +++ b/resource/gnu/java/awt/peer/x/fonts.properties @@ -0,0 +1,61 @@ +# fonts.properties +# Copyright (C) 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Classpath. +# +# GNU Classpath is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Classpath is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Classpath; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA. +# +# Linking this library statically or dynamically with other modules is +# making a combined work based on this library. Thus, the terms and +# conditions of the GNU General Public License cover the whole +# combination. +# +# As a special exception, the copyright holders of this library give you +# permission to link this library with independent modules to produce an +# executable, regardless of the license terms of these independent +# modules, and to copy and distribute the resulting executable under +# terms of your choice, provided that you also meet, for each linked +# independent module, the terms and conditions of the license of that +# module. An independent module is a module which is not derived from +# or based on this library. If you modify this library, you may extend +# this exception to your version of the library, but you are not +# obligated to do so. If you do not wish to do so, delete this +# exception statement from your version. + +serif.plain=-adobe-times-medium-r-normal--*-%d-75-*-p-*-iso8859-1 +serif.bold=-adobe-times-bold-r-normal--*-%d-75-*-p-*-iso8859-1 +serif.italic=-adobe-times-medium-o-normal--*-%d-75-*-p-*-iso8859-1 +serif.bolditalic=-adobe-times-bold-o-normal--*-%d-75-*-p-*-iso8859-1 + +sansserif.plain=-adobe-helvetica-medium-r-normal--*-%d-75-*-p-*-iso8859-1 +sansserif.bold=-adobe-helvetica-bold-r-normal--*-%d-75-*-p-*-iso8859-1 +sansserif.italic=-adobe-helvetica-medium-o-normal--*-%d-75-*-p-*-iso8859-1 +sansserif.bolditalic=-adobe-helvetica-bold-o-normal--*-%d-75-*-p-*-iso8859-1 + +monospaced.plain=-adobe-courier-medium-r-normal--*-%d-75-*-p-*-iso8859-1 +monospaced.bold=-adobe-courier-bold-r-normal--*-%d-75-*-p-*-iso8859-1 +monospaced.italic=-adobe-courier-medium-o-normal--*-%d-75-*-p-*-iso8859-1 +monospaced.bolditalic=-adobe-courier-bold-o-normal--*-%d-75-*-p-*-iso8859-1 + +dialog.plain=-adobe-helvetica-medium-r-normal--*-%d-75-*-p-*-iso8859-1 +dialog.bold=-adobe-helvetica-bold-r-normal--*-%d-75-*-p-*-iso8859-1 +dialog.italic=-adobe-helvetica-medium-o-normal--*-%d-75-*-p-*-iso8859-1 +dialog.bolditalic=-adobe-helvetica-bold-o-normal--*-%d-75-*-p-*-iso8859-1 + +dialoginput.plain=-adobe-helvetica-medium-r-normal--*-%d-75-*-p-*-iso8859-1 +dialoginput.bold=-adobe-helvetica-bold-r-normal--*-%d-75-*-p-*-iso8859-1 +dialoginput.italic=-adobe-helvetica-medium-o-normal--*-%d-75-*-p-*-iso8859-1 +dialoginput.bolditalic=-adobe-helvetica-bold-o-normal--*-%d-75-*-p-*-iso8859-1 diff --git a/resource/gnu/java/util/regex/MessagesBundle.properties b/resource/gnu/java/util/regex/MessagesBundle.properties new file mode 100644 index 000000000..fb2f27c39 --- /dev/null +++ b/resource/gnu/java/util/regex/MessagesBundle.properties @@ -0,0 +1,22 @@ +# Localized error messages for gnu.regexp + +# Prefix for REException messages +error.prefix=At position {0} in regular expression pattern: + +# REException (parse error) messages +repeat.assertion=repeated token is zero-width assertion +repeat.chained=attempted to repeat a token that is already repeated +repeat.no.token=quantifier (?*+{}) without preceding token +repeat.empty.token=repeated token may be empty +unmatched.brace=unmatched brace +unmatched.bracket=unmatched bracket +unmatched.paren=unmatched parenthesis +interval.no.end=unexpected end of interval +class.no.end=unexpected end of character class +subexpr.no.end=unexpected end of subexpression +interval.order=an interval''s minimum is greater than its maximum +interval.error=an interval is empty * or contains illegal characters +ends.with.backslash=backslash at end of pattern + +# RESyntax message +syntax.final=Syntax has been declared final and cannot be modified diff --git a/resource/gnu/java/util/regex/MessagesBundle_fr.properties b/resource/gnu/java/util/regex/MessagesBundle_fr.properties new file mode 100644 index 000000000..99da4e22d --- /dev/null +++ b/resource/gnu/java/util/regex/MessagesBundle_fr.properties @@ -0,0 +1,22 @@ +# Localized error messages for gnu.regexp + +# Prefix for REException messages +error.prefix=A l''index {0} dans le modèle d''expression régulière: + +# REException (parse error) messages +repeat.assertion=l''élément répété est de largeur zéro +repeat.chained=tentative de répétition d''un élément déjà répété +repeat.no.token=quantifieur (?*+{}) sans élément précédent +repeat.empty.token=l''élément répété peut être vide +unmatched.brace=accolade inégalée +unmatched.bracket=crochet inégalé +unmatched.paren=parenthèse inégalée +interval.no.end=fin d''interval non attendue +class.no.end=fin de classe de caractères non attendue +subexpr.no.end=fin de sous-expression non attendue +interval.order=l''interval minimum est supérieur à l''interval maximum +interval.error=l''interval est vide ou contient des caractères illégaux +ends.with.backslash=antislash à la fin du modèle + +# RESyntax message +syntax.final=La syntaxe a été déclarée finale et ne peut pas être modifiée diff --git a/resource/gnu/java/util/regex/MessagesBundle_it.properties b/resource/gnu/java/util/regex/MessagesBundle_it.properties new file mode 100644 index 000000000..e5ec9e679 --- /dev/null +++ b/resource/gnu/java/util/regex/MessagesBundle_it.properties @@ -0,0 +1,31 @@ +# Localized error messages for gnu.regexp, in Italian. +# $Id: MessagesBundle_it.properties,v 1.1.2.1 2006-07-23 21:28:36 gnu_andrew Exp $ +# Messaggi italiani per gnu.regexp. +# +# Attenzione: Questa traduzione fu scritto da un italo-americano. +# Per favore correggete l'italiano bestemmiato e mandate i patch +# al listo <classpath at gnu dot org>. +# +# @author Steven Augart <steve at watson dot ibm dot com>, <steve at augart dot com> + +# Prefix for REException messages +error.prefix=Al indice {0} nel modello dell''espressione regulare: + +# REException (parse error) messages +repeat.assertion=l''elemento ripetuto ha larghezza zero +repeat.chained=prova di ripetere un elemento già ripetuto +repeat.no.token=quantificatore (?*+{}) senza elemento precedente +repeat.empty.token=l''elemento ripetuto può essere vuoto +unmatched.brace=parentesi quadra senza corrispondente +unmatched.bracket=graffa senza corrispondente +unmatched.paren=parentesi senza corrispondente +interval.no.end=la fine d''intervallo è imprevista +class.no.end=la fine della classe di caratteri è imprevista +subexpr.no.end=la fine del sub-espressione è imprevista +interval.order=il valore minimo d''intervallo è piú grande del suo valore massimo +interval.error=l''intervallo è vuoto o contiene caratteri impermessibili +# Non so come si dice "backslash" in italiano. +ends.with.backslash=il modello finisce con un backslash (il carattere "\") + +# RESyntax message +syntax.final=La sintassi è dichiarata "final" (finale) e non si può modificarla diff --git a/resource/java/security/classpath.security b/resource/java/security/classpath.security index 13d691bfe..0d69f25c8 100644 --- a/resource/java/security/classpath.security +++ b/resource/java/security/classpath.security @@ -1,5 +1,5 @@ # classpath.security -# Copyright (C) 2002 Free Software Foundation, Inc. +# Copyright (C) 2002, 2006 Free Software Foundation, Inc. # # This file is part of GNU Classpath. # @@ -41,3 +41,7 @@ security.provider.2=gnu.javax.crypto.jce.GnuCrypto security.provider.3=gnu.javax.crypto.jce.GnuSasl security.provider.4=gnu.javax.net.ssl.provider.Jessie security.provider.5=gnu.javax.security.auth.callback.GnuCallbacks + +# The VM-wide default callback handler class name. MUST be a subclass of +# javax.security.auth.callback.CallbackHandler +auth.login.defaultCallbackHandler=gnu.javax.security.auth.callback.DefaultCallbackHandler diff --git a/tools/gnu/classpath/tools/jarsigner/SFHelper.java b/tools/gnu/classpath/tools/jarsigner/SFHelper.java index 0d8c2eb44..83e87b843 100644 --- a/tools/gnu/classpath/tools/jarsigner/SFHelper.java +++ b/tools/gnu/classpath/tools/jarsigner/SFHelper.java @@ -63,10 +63,13 @@ import java.security.PrivateKey; import java.security.cert.CRLException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509CRL; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -265,6 +268,30 @@ public class SFHelper Set signerInfos = new HashSet(); X509Certificate cert = (X509Certificate) certificates[0]; + try + { + cert.checkValidity(); + } + catch (CertificateExpiredException x) + { + String issuerName = getIssuerName(cert); + String subjectName = getSubjectName(cert); + Date notAfterDate = getNotAfterDate(cert); + System.out.println(Messages.getFormattedString("SFHelper.0", //$NON-NLS-1$ + new Object[] { issuerName, + subjectName, + notAfterDate })); + } + catch (CertificateNotYetValidException x) + { + String issuerName = getIssuerName(cert); + String subjectName = getSubjectName(cert); + Date notBeforeDate = getNotBeforeDate(cert); + System.out.println(Messages.getFormattedString("SFHelper.11", //$NON-NLS-1$ + new Object[] { issuerName, + subjectName, + notBeforeDate })); + } X500Principal issuer = cert.getIssuerX500Principal(); BigInteger serialNumber = cert.getSerialNumber(); byte[] authenticatedAttributes = null; @@ -379,4 +406,100 @@ public class SFHelper this.state = FINISHED; } + + /** + * Given an X.509 certificate this method returns the string representation of + * the Issuer Distinguished Name. + * + * @param cert an X.509 certificate. + * @return the string representation of the Issuer's DN. + */ + private String getIssuerName(X509Certificate cert) + { + X500Principal xp = cert.getIssuerX500Principal(); + if (xp == null) + { + if (Configuration.DEBUG) + log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$ + + ", has null Issuer. Return [unknown]"); //$NON-NLS-1$ + return Messages.getString("SFHelper.14"); //$NON-NLS-1$ + } + String result = xp.getName(); + if (result == null) + { + if (Configuration.DEBUG) + log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$ + + ", has an Issuer with null DN. Return [unnamed]"); //$NON-NLS-1$ + return Messages.getString("SFHelper.17"); //$NON-NLS-1$ + } + return result; + } + + /** + * Given an X.509 certificate this method returns the string representation of + * the Subject Distinguished Name. + * + * @param cert an X.509 certificate. + * @return the string representation of the Subject's DN. + */ + private String getSubjectName(X509Certificate cert) + { + X500Principal xp = cert.getSubjectX500Principal(); + if (xp == null) + { + if (Configuration.DEBUG) + log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$ + + ", has null Subject. Return [unknown]"); //$NON-NLS-1$ + return Messages.getString("SFHelper.14"); //$NON-NLS-1$ + } + String result = xp.getName(); + if (result == null) + { + if (Configuration.DEBUG) + log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$ + + ", has a Subject with null DN. Return [unnamed]"); //$NON-NLS-1$ + return Messages.getString("SFHelper.17"); //$NON-NLS-1$ + } + return result; + } + + /** + * Given an X.509 certificate this method returns the end validity date of + * this certificate. + * + * @param cert an X.509 certificate. + * @return the date when this certificate stops being valid. + */ + private Date getNotAfterDate(X509Certificate cert) + { + Date result = cert.getNotAfter(); + if (result == null) + { + if (Configuration.DEBUG) + log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$ + + ", has null start-validity date. Return epoch"); //$NON-NLS-1$ + return new Date(0); + } + return result; + } + + /** + * Given an X.509 certificate this method returns the start validity date of + * this certificate. + * + * @param cert an X.509 certificate. + * @return the date when this certificate starts being valid. + */ + private Date getNotBeforeDate(X509Certificate cert) + { + Date result = cert.getNotBefore(); + if (result == null) + { + if (Configuration.DEBUG) + log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$ + + ", has null end-validity date. Return epoch"); //$NON-NLS-1$ + return new Date(0); + } + return result; + } } diff --git a/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java b/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java index e32e8f0ac..723d4e897 100644 --- a/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java +++ b/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java @@ -106,6 +106,15 @@ final class VMMemoryPoolMXBeanImpl static native MemoryUsage getPeakUsage(String name); /** + * Returns the type of memory used by the specified pool. + * The value must be either "HEAP" or "NON_HEAP". + * + * @param name the name of the pool to obtain statistics on. + * @return the type of the given pool. + */ + static native String getType(String name); + + /** * Returns the current usage level of the specified pool. * This is only called if the pool is valid. * |