|
From: <ls...@us...> - 2007-01-27 09:39:36
|
Revision: 3088
http://jnode.svn.sourceforge.net/jnode/?rev=3088&view=rev
Author: lsantha
Date: 2007-01-27 01:39:31 -0800 (Sat, 27 Jan 2007)
Log Message:
-----------
Classpath patches.
Modified Paths:
--------------
trunk/core/src/classpath/gnu/gnu/java/awt/peer/GLightweightPeer.java
trunk/core/src/classpath/java/java/awt/CheckboxMenuItem.java
trunk/core/src/classpath/java/java/awt/MenuItem.java
trunk/core/src/classpath/java/java/awt/image/AffineTransformOp.java
trunk/core/src/classpath/java/java/awt/image/BandCombineOp.java
trunk/core/src/classpath/java/java/awt/image/ColorConvertOp.java
trunk/core/src/classpath/java/java/awt/image/ColorModel.java
trunk/core/src/classpath/java/java/awt/image/ConvolveOp.java
trunk/core/src/classpath/java/java/awt/image/ImageConsumer.java
trunk/core/src/classpath/java/java/awt/image/ImageFilter.java
trunk/core/src/classpath/java/java/awt/image/LookupOp.java
trunk/core/src/classpath/java/java/awt/image/PixelGrabber.java
trunk/core/src/classpath/java/java/awt/image/RGBImageFilter.java
trunk/core/src/classpath/java/java/awt/image/Raster.java
trunk/core/src/classpath/java/java/awt/image/RenderedImage.java
trunk/core/src/classpath/java/java/awt/image/ReplicateScaleFilter.java
trunk/core/src/classpath/java/java/awt/image/RescaleOp.java
trunk/core/src/classpath/java/java/awt/image/SampleModel.java
trunk/core/src/classpath/java/java/awt/image/SinglePixelPackedSampleModel.java
trunk/core/src/classpath/java/java/awt/image/WritableRaster.java
trunk/core/src/classpath/java/java/text/DateFormat.java
trunk/core/src/classpath/java/java/text/DateFormatSymbols.java
trunk/core/src/classpath/java/java/text/DecimalFormatSymbols.java
trunk/core/src/classpath/java/java/text/NumberFormat.java
trunk/core/src/classpath/java/java/util/Arrays.java
trunk/core/src/classpath/javax/javax/swing/ToolTipManager.java
trunk/core/src/classpath/javax/javax/swing/TransferHandler.java
trunk/core/src/classpath/tools/gnu/classpath/tools/jarsigner/JarVerifier.java
trunk/core/src/classpath/tools/gnu/classpath/tools/jarsigner/Main.java
trunk/core/src/classpath/tools/gnu/classpath/tools/jarsigner/Messages.java
trunk/core/src/classpath/tools/gnu/classpath/tools/jarsigner/SFHelper.java
trunk/core/src/classpath/tools/gnu/classpath/tools/native2ascii/Native2ASCII.java
Added Paths:
-----------
trunk/core/src/classpath/gnu/gnu/java/awt/ComponentReshapeEvent.java
trunk/core/src/classpath/gnu/gnu/java/awt/dnd/
trunk/core/src/classpath/gnu/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java
trunk/core/src/classpath/java/java/text/spi/DateFormatProvider.java
trunk/core/src/classpath/java/java/text/spi/DecimalFormatSymbolsProvider.java
trunk/core/src/classpath/java/java/text/spi/NumberFormatProvider.java
trunk/core/src/classpath/javax/javax/management/AttributeChangeNotification.java
Added: trunk/core/src/classpath/gnu/gnu/java/awt/ComponentReshapeEvent.java
===================================================================
--- trunk/core/src/classpath/gnu/gnu/java/awt/ComponentReshapeEvent.java (rev 0)
+++ trunk/core/src/classpath/gnu/gnu/java/awt/ComponentReshapeEvent.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -0,0 +1,85 @@
+/* WindowResizeEvent.java -- Used to synchronize the AWT and peer sizes
+ 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;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+
+/**
+ * This is used to update the AWT's knowledge about a Window's size when
+ * the user changes the window bounds.
+ *
+ * This event is _not_ posted to the eventqueue, but rather dispatched directly
+ * via Window.dispatchEvent(). It is the cleanest way we could find to update
+ * the AWT's knowledge of the window size. Small testprograms showed the
+ * following:
+ * - Component.reshape() and its derivatives are _not_ called. This makes sense
+ * as it could end up in loops,because this calls back into the peers.
+ * - Intercepting event dispatching for any events in
+ * EventQueue.dispatchEvent() showed that the size is still updated. So it
+ * is not done via an event dispatched over the eventqueue.
+ *
+ * Possible other candidates for implementation would have been:
+ * - Call a (private) callback method in Window/Component from the native
+ * side.
+ * - Call a (private) callback method in Window/Component via reflection.
+ *
+ * Both is uglier than sending this event directly. Note however that this
+ * is impossible to test, as Component.dispatchEvent() is final and can't be
+ * intercepted from outside code. But this impossibility to test the issue from
+ * outside code also means that this shouldn't raise any compatibility issues.
+ */
+public class ComponentReshapeEvent
+ extends AWTEvent
+{
+
+ public int x;
+ public int y;
+ public int width;
+ public int height;
+
+ public ComponentReshapeEvent(Component c, int x, int y, int width, int height)
+ {
+ super(c, 1999);
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+}
Added: trunk/core/src/classpath/gnu/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java
===================================================================
--- trunk/core/src/classpath/gnu/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java (rev 0)
+++ trunk/core/src/classpath/gnu/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -0,0 +1,172 @@
+/* GtkMouseDragGestureRecognizer.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.java.awt.dnd;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.MouseDragGestureRecognizer;
+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);
+ }
+
+ public GtkMouseDragGestureRecognizer (DragSource ds, Component c, int act)
+ {
+ this(ds, c, act, null);
+ }
+
+ public GtkMouseDragGestureRecognizer (DragSource ds, Component c, int act,
+ DragGestureListener dgl)
+ {
+ super(ds, c, act, dgl);
+ }
+
+ public void registerListeners ()
+ {
+ super.registerListeners();
+ }
+
+ public void unregisterListeners ()
+ {
+ super.unregisterListeners();
+ }
+
+ public void mouseClicked (MouseEvent e)
+ {
+ // Nothing to do here.
+ }
+
+ public void mousePressed (MouseEvent e)
+ {
+ events.clear();
+ if (getDropActionFromEvent(e) != DnDConstants.ACTION_NONE)
+ appendEvent(e);
+ }
+
+ public void mouseReleased (MouseEvent e)
+ {
+ events.clear();
+ }
+
+ public void mouseEntered (MouseEvent e)
+ {
+ events.clear();
+ }
+
+ public void mouseExited(MouseEvent e)
+ {
+ if (!events.isEmpty())
+ if (getDropActionFromEvent(e) == DnDConstants.ACTION_NONE)
+ events.clear();
+ }
+
+ public void mouseDragged(MouseEvent e)
+ {
+ 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)
+ {
+ // 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;
+ }
+}
Modified: trunk/core/src/classpath/gnu/gnu/java/awt/peer/GLightweightPeer.java
===================================================================
--- trunk/core/src/classpath/gnu/gnu/java/awt/peer/GLightweightPeer.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/gnu/gnu/java/awt/peer/GLightweightPeer.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -163,8 +163,10 @@
public FontMetrics getFontMetrics(Font f)
{
- // Nothing to do here for lightweights.
- return null;
+ // We shouldn't end up here, but if we do we can still try do something
+ // reasonable.
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ return tk.getFontMetrics(f);
}
/* Returning null here tells the Component object that called us to
@@ -201,7 +203,31 @@
public void handleEvent(AWTEvent e)
{
- // Nothing to do here for lightweights.
+ // This can only happen when an application posts a PaintEvent for
+ // a lightweight component directly. We still support painting for
+ // this case.
+ if (e instanceof PaintEvent)
+ {
+ PaintEvent pe = (PaintEvent) e;
+ Component target = (Component) e.getSource();
+ if (target != null && target.isShowing())
+ {
+ Graphics g = target.getGraphics();
+ if (g != null)
+ {
+ try
+ {
+ Rectangle clip = pe.getUpdateRect();
+ g.setClip(clip);
+ target.paint(g);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ }
+ }
}
public void hide()
Modified: trunk/core/src/classpath/java/java/awt/CheckboxMenuItem.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/CheckboxMenuItem.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/CheckboxMenuItem.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -318,7 +318,7 @@
* @exception ClassCastException If listenerType doesn't specify a class or
* interface that implements java.util.EventListener.
*/
- public EventListener[] getListeners (Class listenerType)
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
{
if (listenerType == ItemListener.class)
return AWTEventMulticaster.getListeners (item_listeners, listenerType);
Modified: trunk/core/src/classpath/java/java/awt/MenuItem.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/MenuItem.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/MenuItem.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -523,11 +523,11 @@
* ClassClassException is thrown.
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == ActionListener.class)
- return getActionListeners();
- return (EventListener[]) Array.newInstance(listenerType, 0);
+ return (T[]) getActionListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
}
/*************************************************************************/
Modified: trunk/core/src/classpath/java/java/awt/image/AffineTransformOp.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/AffineTransformOp.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/AffineTransformOp.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -39,6 +39,7 @@
package java.awt.image;
import java.awt.Graphics2D;
+import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
@@ -48,8 +49,11 @@
import java.util.Arrays;
/**
- * This class performs affine transformation between two images or
- * rasters in 2 dimensions.
+ * AffineTransformOp performs matrix-based transformations (translations,
+ * scales, flips, rotations, and shears).
+ *
+ * If interpolation is required, nearest neighbour, bilinear, and bicubic
+ * methods are available.
*
* @author Olga Rodimina (rod...@re...)
* @author Francis Kung (fk...@re...)
@@ -115,14 +119,14 @@
}
/**
- * Creates empty BufferedImage with the size equal to that of the
- * transformed image and correct number of bands. The newly created
+ * Creates a new BufferedImage with the size equal to that of the
+ * transformed image and the correct number of bands. The newly created
* image is created with the specified ColorModel.
- * If the ColorModel is equal to null, an appropriate ColorModel is used.
+ * If a ColorModel is not specified, an appropriate ColorModel is used.
*
- * @param src source image
- * @param destCM color model for the destination image
- * @return new compatible destination image
+ * @param src the source image.
+ * @param destCM color model for the destination image (can be null).
+ * @return a new compatible destination image.
*/
public BufferedImage createCompatibleDestImage (BufferedImage src,
ColorModel destCM)
@@ -145,21 +149,18 @@
}
/**
- * Creates empty WritableRaster with the size equal to the transformed
- * source raster and correct number of bands
+ * Creates a new WritableRaster with the size equal to the transformed
+ * source raster and correct number of bands .
*
- * @param src source raster
- * @throws RasterFormatException if resulting width or height of raster is 0
- * @return new compatible raster
+ * @param src the source raster.
+ * @throws RasterFormatException if resulting width or height of raster is 0.
+ * @return a new compatible raster.
*/
public WritableRaster createCompatibleDestRaster (Raster src)
{
Rectangle2D rect = getBounds2D(src);
- // throw RasterFormatException if resulting width or height of the
- // transformed raster is 0
-
- if (rect.getWidth () == 0 || rect.getHeight () == 0)
+ if (rect.getWidth() == 0 || rect.getHeight() == 0)
throw new RasterFormatException("width or height is 0");
return src.createCompatibleWritableRaster((int) rect.getWidth(),
@@ -175,24 +176,22 @@
* @param dst destination image
* @throws IllegalArgumentException if the source and destination image are
* the same
- * @return transformed source image
+ * @return transformed source image.
*/
public final BufferedImage filter (BufferedImage src, BufferedImage dst)
{
-
if (dst == src)
- throw new IllegalArgumentException ("src image cannot be the same as " +
- "the dst image");
+ throw new IllegalArgumentException("src image cannot be the same as "
+ + "the dst image");
// If the destination image is null, then use a compatible BufferedImage
if (dst == null)
dst = createCompatibleDestImage(src, null);
- Graphics2D gr = (Graphics2D) dst.createGraphics ();
- gr.setRenderingHints (hints);
- gr.drawImage (src, transform, null);
+ Graphics2D gr = (Graphics2D) dst.createGraphics();
+ gr.setRenderingHints(hints);
+ gr.drawImage(src, transform, null);
return dst;
-
}
/**
@@ -204,10 +203,11 @@
* @param dst destination raster
* @throws IllegalArgumentException if the source and destination are not
* compatible
- * @return transformed raster
+ * @return transformed raster.
*/
- public final WritableRaster filter (Raster src, WritableRaster dst)
+ public final WritableRaster filter(Raster src, WritableRaster dst)
{
+ // Initial checks
if (dst == src)
throw new IllegalArgumentException("src image cannot be the same as"
+ " the dst image");
@@ -219,6 +219,24 @@
throw new IllegalArgumentException("src and dst must have same number"
+ " of bands");
+ // Optimization for rasters that can be represented in the RGB colormodel:
+ // wrap the rasters in images, and let Cairo do the transformation
+ if (ColorModel.getRGBdefault().isCompatibleSampleModel(src.getSampleModel())
+ && ColorModel.getRGBdefault().isCompatibleSampleModel(dst.getSampleModel()))
+ {
+ WritableRaster src2 = Raster.createWritableRaster(src.getSampleModel(),
+ src.getDataBuffer(),
+ new Point(src.getMinX(),
+ src.getMinY()));
+ BufferedImage iSrc = new BufferedImage(ColorModel.getRGBdefault(),
+ src2, false, null);
+ BufferedImage iDst = new BufferedImage(ColorModel.getRGBdefault(), dst,
+ false, null);
+
+ return filter(iSrc, iDst).getRaster();
+ }
+
+ // Otherwise, we need to do the transformation in java code...
// Create arrays to hold all the points
double[] dstPts = new double[dst.getHeight() * dst.getWidth() * 2];
double[] srcPts = new double[dst.getHeight() * dst.getWidth() * 2];
@@ -287,7 +305,7 @@
}
/**
- * Returns interpolation type used during transformations
+ * Returns interpolation type used during transformations.
*
* @return interpolation type
*/
@@ -319,7 +337,7 @@
/**
* Returns rendering hints that are used during transformation.
*
- * @return rendering hints
+ * @return the rendering hints used in this Op.
*/
public final RenderingHints getRenderingHints ()
{
@@ -330,7 +348,7 @@
* Returns transform used in transformation between source and destination
* image.
*
- * @return transform
+ * @return the transform used in this Op.
*/
public final AffineTransform getTransform ()
{
@@ -377,6 +395,18 @@
{
Rectangle srcbounds = src.getBounds();
+ Object xyarr = null;
+ Object xp1arr = null;
+ Object yp1arr = null;
+ Object xyp1arr = null;
+
+ double xy;
+ double xp1;
+ double yp1;
+ double xyp1;
+
+ double[] result = new double[src.getNumBands()];
+
// For all points in the destination raster, use bilinear interpolation
// to find the value from the corrosponding source points
for (int i = 0; i < dpts.length; i += 2)
@@ -401,21 +431,64 @@
double xdiff = pts[i] + src.getMinX() - x;
double ydiff = pts[i + 1] + src.getMinY() - y;
- // Run the interpolation for each band
+ // Get surrounding pixels used in interpolation... optimized
+ // to use the smallest datatype possible.
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ xyarr = src.getPixel(x, y, (double[])xyarr);
+ xp1arr = src.getPixel(x+1, y, (double[])xp1arr);
+ yp1arr = src.getPixel(x, y+1, (double[])yp1arr);
+ xyp1arr = src.getPixel(x+1, y+1, (double[])xyp1arr);
+ }
+ else
+ {
+ xyarr = src.getPixel(x, y, (int[])xyarr);
+ xp1arr = src.getPixel(x+1, y, (int[])xp1arr);
+ yp1arr = src.getPixel(x, y+1, (int[])yp1arr);
+ xyp1arr = src.getPixel(x+1, y+1, (int[])xyp1arr);
+ }
+ // using
+ // array[] pixels = src.getPixels(x, y, 2, 2, pixels);
+ // instead of doing four individual src.getPixel() calls
+ // should be faster, but benchmarking shows that it's not...
+
+ // Run interpolation for each band
for (int j = 0; j < src.getNumBands(); j++)
{
- double result = (src.getSampleDouble(x, y, j) * (1 - xdiff)
- + src.getSampleDouble(x + 1, y, j) * xdiff)
- * (1 - ydiff)
- + (src.getSampleDouble(x, y + 1, j)
- * (1 - xdiff)
- + src.getSampleDouble(x + 1, y + 1, j)
- * xdiff)
+ // Pull individual sample values out of array
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ xy = ((double[])xyarr)[j];
+ xp1 = ((double[])xp1arr)[j];
+ yp1 = ((double[])yp1arr)[j];
+ xyp1 = ((double[])xyp1arr)[j];
+ }
+ else
+ {
+ xy = ((int[])xyarr)[j];
+ xp1 = ((int[])xp1arr)[j];
+ yp1 = ((int[])yp1arr)[j];
+ xyp1 = ((int[])xyp1arr)[j];
+ }
+
+ // If all four samples are identical, there's no need to
+ // calculate anything
+ if (xy == xp1 && xy == yp1 && xy == xyp1)
+ result[j] = xy;
+
+ // Run bilinear interpolation formula
+ else
+ result[j] = (xy * (1-xdiff) + xp1 * xdiff)
+ * (1-ydiff)
+ + (yp1 * (1-xdiff) + xyp1 * xdiff)
* ydiff;
- dst.setSample((int) dpts[i] + dst.getMinX(),
- (int) dpts[i + 1] + dst.getMinY(),
- j, result);
}
+
+ dst.setPixel((int)dpts[i] + dst.getMinX(),
+ (int)dpts[i+1] + dst.getMinY(),
+ result);
}
}
}
@@ -434,10 +507,11 @@
double[] pts)
{
Rectangle srcbounds = src.getBounds();
+ double[] result = new double[src.getNumBands()];
+ Object pixels = null;
// For all points on the destination raster, perform bicubic interpolation
// from corrosponding source points
- double[] result = new double[src.getNumBands()];
for (int i = 0; i < dpts.length; i += 2)
{
if (srcbounds.contains((int) Math.round(pts[i]) + src.getMinX(),
@@ -450,7 +524,6 @@
Arrays.fill(result, 0);
for (int m = - 1; m < 3; m++)
- {
for (int n = - 1; n < 3; n++)
{
// R(x) = ( P(x+2)^3 - 4 P(x+1)^3 + 6 P(x)^3 - 4 P(x-1)^3 ) / 6
@@ -459,7 +532,6 @@
// Calculate R(m - dx)
double rx = m - dx + 2;
- if (rx > 0)
r1 += rx * rx * rx;
rx = m - dx + 1;
@@ -509,17 +581,27 @@
else if (srcY < src.getMinY())
srcY = src.getMinY();
- // Calculate once for each band
+ // Calculate once for each band, using the smallest
+ // datatype possible
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ pixels = src.getPixel(srcX, srcY, (double[])pixels);
for (int j = 0; j < result.length; j++)
- result[j] += src.getSample(srcX, srcY, j) * r1 * r2;
+ result[j] += ((double[])pixels)[j] * r1 * r2;
+ }
+ else
+ {
+ pixels = src.getPixel(srcX, srcY, (int[])pixels);
+ for (int j = 0; j < result.length; j++)
+ result[j] += ((int[])pixels)[j] * r1 * r2;
}
}
// Put it all together
- for (int j = 0; j < result.length; j++)
- dst.setSample((int) dpts[i] + dst.getMinX(),
- (int) dpts[i + 1] + dst.getMinY(),
- j, result[j]);
+ dst.setPixel((int)dpts[i] + dst.getMinX(),
+ (int)dpts[i+1] + dst.getMinY(),
+ result);
}
}
}
Modified: trunk/core/src/classpath/java/java/awt/image/BandCombineOp.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/BandCombineOp.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/BandCombineOp.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -40,6 +40,7 @@
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
/**
* Filter Raster pixels by applying a matrix.
@@ -53,6 +54,9 @@
* for the destination. Therefore the destination Raster must contain the
* same number of bands as the number of rows in the filter matrix.
*
+ * This Op assumes that samples are integers; floating point sample types will
+ * be rounded to their nearest integer value during filtering.
+ *
* @author Jerry Quinn (jl...@op...)
*/
public class BandCombineOp implements RasterOp
@@ -109,19 +113,27 @@
throw new IllegalArgumentException("Destination raster is incompatible with source raster");
// Filter the pixels
- float[] spix = new float[matrix[0].length - 1];
- float[] dpix = new float[matrix.length];
+ int[] spix = new int[matrix[0].length - 1];
+ int[] spix2 = new int[matrix[0].length - 1];
+ int[] dpix = new int[matrix.length];
for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
{
// In case matrix rows have implicit translation
- spix[spix.length - 1] = 1.0f;
+ spix[spix.length - 1] = 1;
src.getPixel(x, y, spix);
+
+ // Do not re-calculate if pixel is identical to the last one
+ // (ie, blocks of the same colour)
+ if (!Arrays.equals(spix, spix2))
+ {
+ System.arraycopy(spix, 0, spix2, 0, spix.length);
for (int i = 0; i < matrix.length; i++)
{
dpix[i] = 0;
for (int j = 0; j < matrix[0].length - 1; j++)
- dpix[i] += spix[j] * matrix[i][j];
+ dpix[i] += spix[j] * (int)matrix[i][j];
+ }
}
dest.setPixel(x, y, dpix);
}
Modified: trunk/core/src/classpath/java/java/awt/image/ColorConvertOp.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/ColorConvertOp.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/ColorConvertOp.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -38,6 +38,8 @@
package java.awt.image;
+import gnu.java.awt.Buffers;
+
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
@@ -283,7 +285,8 @@
for (int i = 0; i < spaces.length - 2; i++)
{
WritableRaster tmp = createCompatibleDestRaster(src, spaces[i + 1],
- false);
+ false,
+ src.getTransferType());
copyraster(src, spaces[i], tmp, spaces[i + 1]);
src = tmp;
}
@@ -291,7 +294,8 @@
// The last conversion is done outside of the loop so that we can
// use the dest raster supplied, instead of creating our own temp raster
if (dest == null)
- dest = createCompatibleDestRaster(src, spaces[spaces.length - 1], false);
+ dest = createCompatibleDestRaster(src, spaces[spaces.length - 1], false,
+ DataBuffer.TYPE_BYTE);
copyraster(src, spaces[spaces.length - 2], dest, spaces[spaces.length - 1]);
return dest;
@@ -324,7 +328,8 @@
return new BufferedImage(dstCM,
createCompatibleDestRaster(src.getRaster(),
dstCM.getColorSpace(),
- src.getColorModel().hasAlpha),
+ src.getColorModel().hasAlpha,
+ dstCM.getTransferType()),
src.isPremultiplied, null);
}
@@ -349,7 +354,8 @@
// Create a new raster with the last ColorSpace in the conversion
// chain, and with no alpha (implied)
- return createCompatibleDestRaster(src, spaces[spaces.length-1], false);
+ return createCompatibleDestRaster(src, spaces[spaces.length-1], false,
+ DataBuffer.TYPE_BYTE);
}
/**
@@ -417,11 +423,16 @@
return src.getBounds();
}
- // Copy a source image to a destination image, respecting their colorspaces
- // and performing colorspace conversions if necessary. This is done
- // using Graphics2D in order to use the rendering hints.
+ /**
+ * Copy a source image to a destination image, respecting their colorspaces
+ * and performing colorspace conversions if necessary.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ */
private void copyimage(BufferedImage src, BufferedImage dst)
{
+ // This is done using Graphics2D in order to respect the rendering hints.
Graphics2D gg = dst.createGraphics();
// If no hints are set there is no need to call
@@ -433,8 +444,16 @@
gg.dispose();
}
- // Copy a source raster to a destination raster, performing a colorspace
- // conversion.
+ /**
+ * Copy a source raster to a destination raster, performing a colorspace
+ * conversion between the two. The conversion will respect the
+ * KEY_COLOR_RENDERING rendering hint if one is present.
+ *
+ * @param src The source raster.
+ * @param scs The colorspace of the source raster.
+ * @dst The destination raster.
+ * @dcs The colorspace of the destination raster.
+ */
private void copyraster(Raster src, ColorSpace scs, WritableRaster dst, ColorSpace dcs)
{
float[] sbuf = new float[src.getNumBands()];
@@ -459,11 +478,19 @@
}
}
- // This method creates a compatible color model, given a source image and
- // a colorspace. The choice of ComponentColorModel and DataBuffer.TYPE_BYTE
- // is based on Mauve testing of the reference implementation.
+ /**
+ * This method creates a color model with the same colorspace and alpha
+ * settings as the source image. The created color model will always be a
+ * ComponentColorModel and have a BYTE transfer type.
+ *
+ * @param img The source image.
+ * @param cs The ColorSpace to use.
+ * @return A color model compatible with the source image.
+ */
private ColorModel createCompatibleColorModel(BufferedImage img, ColorSpace cs)
{
+ // The choice of ComponentColorModel and DataBuffer.TYPE_BYTE is based on
+ // Mauve testing of the reference implementation.
return new ComponentColorModel(cs,
img.getColorModel().hasAlpha(),
img.isAlphaPremultiplied(),
@@ -471,13 +498,22 @@
DataBuffer.TYPE_BYTE);
}
- // This method creates a compatible Raster, given a source raster and
- // colorspace.
- private WritableRaster createCompatibleDestRaster(Raster src, ColorSpace cs, boolean hasAlpha)
+ /**
+ * This method creates a compatible Raster, given a source raster, colorspace,
+ * alpha value, and transfer type.
+ *
+ * @param src The source raster.
+ * @param cs The ColorSpace to use.
+ * @param hasAlpha Whether the raster should include a component for an alpha.
+ * @param transferType The size of a single data element.
+ * @return A compatible WritableRaster.
+ */
+ private WritableRaster createCompatibleDestRaster(Raster src, ColorSpace cs,
+ boolean hasAlpha,
+ int transferType)
{
- // The use of a PixelInterleavedSampleModel (and it's parameters) and
- // a DataBufferByte were determined using mauve tests, based on the
- // reference implementation
+ // The use of a PixelInterleavedSampleModel weas determined using mauve
+ // tests, based on the reference implementation
int numComponents = cs.getNumComponents();
if (hasAlpha)
@@ -487,13 +523,15 @@
for (int i = 0; i < offsets.length; i++)
offsets[i] = i;
- return new WritableRaster(new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
+ DataBuffer db = Buffers.createBuffer(transferType,
+ src.getWidth() * src.getHeight() * numComponents,
+ 1);
+ return new WritableRaster(new PixelInterleavedSampleModel(transferType,
src.getWidth(),
src.getHeight(),
numComponents,
numComponents * src.getWidth(),
offsets),
- new DataBufferByte(src.getWidth() * src.getHeight() * numComponents, 1),
- new Point(src.getMinX(), src.getMinY()));
+ db, new Point(src.getMinX(), src.getMinY()));
}
}
Modified: trunk/core/src/classpath/java/java/awt/image/ColorModel.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/ColorModel.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/ColorModel.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -119,12 +119,8 @@
*/
public ColorModel(int bits)
{
- // @classpath-bugfix Fix difference between Sun's class and this class.
- //this(bits * 4, // total bits, sRGB, four channels
- this(bits, // total bits, sRGB, four channels
- //nArray(bits, 4), // bits for each channel
- nArray(bits / 4, 4), // bits for each channel
- // @classpath-bugfix-end
+ this(bits * 4, // total bits, sRGB, four channels
+ nArray(bits, 4), // bits for each channel
ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
true, // has alpha
false, // not premultiplied
@@ -628,40 +624,40 @@
return cspace;
}
- // Typically overridden
public ColorModel coerceData(WritableRaster raster,
boolean isAlphaPremultiplied)
{
- if (this.isAlphaPremultiplied == isAlphaPremultiplied || ! hasAlpha)
- return this;
+ // This method should always be overridden, but is not abstract.
+ throw new UnsupportedOperationException();
+ }
+ protected void coerceDataWorker(WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
int w = raster.getWidth();
int h = raster.getHeight();
int x = raster.getMinX();
int y = raster.getMinY();
- int size = w*h;
+ int size = w * h;
int numColors = getNumColorComponents();
int numComponents = getNumComponents();
- int alphaScale = (1<<getComponentSize(numColors)) - 1;
+ int alphaScale = (1 << getComponentSize(numColors)) - 1;
double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);
- for (int i=0; i<size; i++)
+ for (int i = 0; i < size; i++)
{
- double alpha = pixels[i*numComponents+numColors]*alphaScale;
- for (int c=0; c<numColors; c++)
+ double alpha = pixels[i * numComponents + numColors] / alphaScale;
+ for (int c = 0; c < numColors; c++)
{
- int offset = i*numComponents+c;
+ int offset = i * numComponents + c;
if (isAlphaPremultiplied)
- pixels[offset] = pixels[offset]/alpha;
+ pixels[offset] = Math.round(pixels[offset] * alpha);
else
- pixels[offset] = pixels[offset]*alpha;
+ pixels[offset] = Math.round(pixels[offset] / alpha);
}
}
raster.setPixels(0, 0, w, h, pixels);
-
- // FIXME: what can we return?
- return null;
}
/**
Modified: trunk/core/src/classpath/java/java/awt/image/ConvolveOp.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/ConvolveOp.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/ConvolveOp.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -38,7 +38,6 @@
package java.awt.image;
-import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -51,11 +50,13 @@
* with elements in the kernel to compute a new pixel.
*
* Each band in a Raster is convolved and copied to the destination Raster.
+ * For BufferedImages, convolution is applied to all components. Color
+ * conversion will be applied if needed.
*
- * For BufferedImages, convolution is applied to all components. If the
- * source is not premultiplied, the data will be premultiplied before
- * convolving. Premultiplication will be undone if the destination is not
- * premultiplied. Color conversion will be applied if needed.
+ * Note that this filter ignores whether the source or destination is alpha
+ * premultiplied. The reference spec states that data will be premultiplied
+ * prior to convolving and divided back out afterwards (if needed), but testing
+ * has shown that this is not the case with their implementation.
*
* @author jl...@op...
*/
@@ -104,59 +105,83 @@
hints = null;
}
-
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage,
- * java.awt.image.BufferedImage)
+ /**
+ * Converts the source image using the kernel specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source and destination BufferedImage (if one is supplied) must have
+ * the same dimensions.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The convolved image.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst)
{
if (src == dst)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Source and destination images " +
+ "cannot be the same.");
if (dst == null)
dst = createCompatibleDestImage(src, src.getColorModel());
// Make sure source image is premultiplied
BufferedImage src1 = src;
- if (!src.isPremultiplied)
+ // The spec says we should do this, but mauve testing shows that Sun's
+ // implementation does not check this.
+ /*
+ if (!src.isAlphaPremultiplied())
{
src1 = createCompatibleDestImage(src, src.getColorModel());
src.copyData(src1.getRaster());
src1.coerceData(true);
}
+ */
BufferedImage dst1 = dst;
- if (!src.getColorModel().equals(dst.getColorModel()))
+ if (src1.getColorModel().getColorSpace().getType() != dst.getColorModel().getColorSpace().getType())
dst1 = createCompatibleDestImage(src, src.getColorModel());
filter(src1.getRaster(), dst1.getRaster());
+ // Since we don't coerceData above, we don't need to divide it back out.
+ // This is wrong (one mauve test specifically tests converting a non-
+ // premultiplied image to a premultiplied image, and it shows that Sun
+ // simply ignores the premultipled flag, contrary to the spec), but we
+ // mimic it for compatibility.
+ /*
+ if (! dst.isAlphaPremultiplied())
+ dst1.coerceData(false);
+ */
+
+ // Convert between color models if needed
if (dst1 != dst)
- {
- // Convert between color models.
- // TODO Check that premultiplied alpha is handled correctly here.
- Graphics2D gg = dst.createGraphics();
- gg.setRenderingHints(hints);
- gg.drawImage(dst1, 0, 0, null);
- gg.dispose();
- }
+ new ColorConvertOp(hints).filter(dst1, dst);
return dst;
}
- /* (non-Javadoc)
- * @see
- * java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage,
- * java.awt.image.ColorModel)
+ /**
+ * Creates an empty BufferedImage with the size equal to the source and the
+ * correct number of bands. The new image is created with the specified
+ * ColorModel, or if no ColorModel is supplied, an appropriate one is chosen.
+ *
+ * @param src The source image.
+ * @param dstCM A color model for the destination image (may be null).
+ * @return The new compatible destination image.
*/
public BufferedImage createCompatibleDestImage(BufferedImage src,
ColorModel dstCM)
{
- // FIXME: set properties to those in src
+ if (dstCM != null)
return new BufferedImage(dstCM,
src.getRaster().createCompatibleWritableRaster(),
- src.isPremultiplied, null);
+ src.isAlphaPremultiplied(), null);
+
+ return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
}
/* (non-Javadoc)
@@ -168,6 +193,8 @@
}
/**
+ * Get the edge condition for this Op.
+ *
* @return The edge condition.
*/
public int getEdgeCondition()
@@ -185,9 +212,22 @@
return (Kernel) kernel.clone();
}
- /* (non-Javadoc)
- * @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
- * java.awt.image.WritableRaster)
+ /**
+ * Converts the source raster using the kernel specified in the constructor.
+ * The resulting raster is stored in the destination raster if one is
+ * provided; otherwise a new WritableRaster is created and returned.
+ *
+ * If the convolved value for a sample is outside the range of [0-255], it
+ * will be clipped.
+ *
+ * The source and destination raster (if one is supplied) cannot be the same,
+ * and must also have the same dimensions.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @throws IllegalArgumentException if the rasters identical.
+ * @throws ImagingOpException if the convolution is not possible.
+ * @return The transformed raster.
*/
public final WritableRaster filter(Raster src, WritableRaster dest)
{
@@ -209,6 +249,11 @@
int top = kernel.getYOrigin();
int bottom = Math.max(kHeight - top - 1, 0);
+ // Calculate max sample values for clipping
+ int[] maxValue = src.getSampleModel().getSampleSize();
+ for (int i = 0; i < maxValue.length; i++)
+ maxValue[i] = (int)Math.pow(2, maxValue[i]) - 1;
+
// process the region that is reachable...
int regionW = src.width - left - right;
int regionH = src.height - top - bottom;
@@ -229,6 +274,13 @@
// 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.
+
+ // This clipping is is undocumented, but determined by testing.
+ if (v > maxValue[b])
+ v = maxValue[b];
+ else if (v < 0)
+ v = 0;
+
dest.setSample(x + kernel.getXOrigin(), y + kernel.getYOrigin(),
b, v);
}
@@ -310,13 +362,14 @@
return src.getBounds();
}
- /** Return corresponding destination point for source point.
+ /**
+ * Returns the corresponding destination point for a source point. Because
+ * this is not a geometric operation, the destination and source points will
+ * be identical.
*
- * ConvolveOp will return the value of src unchanged.
* @param src The source point.
- * @param dst The destination point.
- * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
- * java.awt.geom.Point2D)
+ * @param dst The transformed destination point.
+ * @return The transformed destination point.
*/
public final Point2D getPoint2D(Point2D src, Point2D dst)
{
Modified: trunk/core/src/classpath/java/java/awt/image/ImageConsumer.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/ImageConsumer.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/ImageConsumer.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -136,7 +136,7 @@
*
* @param props the list of properties associated with this image
*/
- void setProperties(Hashtable props);
+ void setProperties(Hashtable<?,?> props);
/**
* This <code>ColorModel</code> should indicate the model used by
Modified: trunk/core/src/classpath/java/java/awt/image/ImageFilter.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/ImageFilter.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/ImageFilter.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -104,12 +104,8 @@
*/
public ImageFilter getFilterInstance(ImageConsumer ic)
{
- if ( ic == null )
- throw new IllegalArgumentException("null argument for ImageFilter.getFilterInstance(ImageConsumer)");
-
- consumer = ic;
ImageFilter f = (ImageFilter)clone();
- consumer = null;
+ f.consumer = ic;
return f;
}
@@ -125,7 +121,6 @@
*/
public void setDimensions(int width, int height)
{
- if (consumer != null)
consumer.setDimensions(width, height);
}
@@ -135,11 +130,16 @@
*
* @param props the list of properties associated with this image
*/
- public void setProperties(Hashtable props)
+ public void setProperties(Hashtable<?,?> props)
{
- props.put("filters", "ImageFilter");
- if (consumer != null)
- consumer.setProperties(props);
+ Hashtable copy = (Hashtable) props.clone();
+ Object o = copy.get("filters");
+ if (o == null)
+ copy.put("filters", toString());
+ else if (o instanceof String)
+ copy.put("filters", ((String) o) + toString());
+
+ consumer.setProperties(copy);
}
/**
@@ -148,10 +148,11 @@
* method of the consumer is called with the specified <code>model</code>.
*
* @param model the color model to be used most often by setPixels
- * @see ColorModel */
+ *
+ * @see ColorModel
+ */
public void setColorModel(ColorModel model)
{
- if (consumer != null)
consumer.setColorModel(model);
}
@@ -167,7 +168,6 @@
*/
public void setHints(int flags)
{
- if (consumer != null)
consumer.setHints(flags);
}
@@ -186,9 +186,9 @@
* @param scansize the width to use in extracting pixels from the <code>pixels</code> array
*/
public void setPixels(int x, int y, int w, int h,
- ColorModel model, byte[] pixels, int offset, int scansize)
+ ColorModel model, byte[] pixels, int offset,
+ int scansize)
{
- if (consumer != null)
consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
}
@@ -207,9 +207,9 @@
* @param scansize the width to use in extracting pixels from the <code>pixels</code> array
*/
public void setPixels(int x, int y, int w, int h,
- ColorModel model, int[] pixels, int offset, int scansize)
+ ColorModel model, int[] pixels, int offset,
+ int scansize)
{
- if (consumer != null)
consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
}
@@ -221,8 +221,6 @@
*/
public void imageComplete(int status)
{
- if (consumer != null)
consumer.imageComplete(status);
}
}
-
Modified: trunk/core/src/classpath/java/java/awt/image/LookupOp.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/image/LookupOp.java 2007-01-27 07:54:10 UTC (rev 3087)
+++ trunk/core/src/classpath/java/java/awt/image/LookupOp.java 2007-01-27 09:39:31 UTC (rev 3088)
@@ -38,7 +38,6 @@
package java.awt.image;
-import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -67,7 +66,8 @@
private LookupTable lut;
private RenderingHints hints;
- /** Construct a new LookupOp.
+ /**
+ * Construct a new LookupOp using the given LookupTable.
*
* @param lookup LookupTable to use.
* @param hints Rendering hints (can be null).
@@ -78,16 +78,40 @@
this.hints = hints;
}
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
+ /**
+ * Converts the source image using the lookup table specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source image cannot use an IndexColorModel, and the destination image
+ * (if one is provided) must have the same size.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @throws ArrayIndexOutOfBoundsException if a pixel in the source is not
+ * contained in the LookupTable.
+ * @return The convolved image.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst)
{
if (src.getColorModel() instanceof IndexColorModel)
throw new IllegalArgumentException("LookupOp.filter: IndexColorModel "
+ "not allowed");
+
+ if (lut.getNumComponents() != 1
+ && lut.getNumComponents() != src.getColorModel().getNumComponents()
+ && lut.getNumComponents() != src.getColorModel().getNumColorComponents())
+ throw new IllegalArgumentException("LookupOp.filter: Incompatible " +
+ "lookup table and source image");
+
if (dst == null)
- dst = createCompatibleDestImage(src, src.getColorModel());
+ dst = createCompatibleDestImage(src, null);
+
+ else if (src.getHeight() != dst.getHeight() || src.getWidth() != dst.getWidth())
+ throw new IllegalArgumentException("Source and destination images are " +
+ "different sizes.");
// Set up for potential colormodel mismatch
BufferedImage tgt;
@@ -116,15 +140,23 @@
sr.getPixel(x, y, dbuf);
System.arraycopy(dbuf, 0, tmp, 0, tmpBands);
dr.setPixel(x, y, lut.lookupPixel(tmp, dbuf));
+
+ /* The reference implementation does not use LookupTable.lookupPixel,
+ * but rather it seems to copy the table into a native array. The
+ * effect of this (a probable bug in their implementation) is that
+ * an out-of-bounds lookup on a ByteLookupTable will *not* throw an
+ * out of bounds exception, but will instead return random garbage.
+ * A bad lookup on a ShortLookupTable, however, will throw an
+ * exception.
+ *
+ * Instead of mimicing this behaviour, we always throw an
+ * ArrayOutofBoundsException by virtue of using
+ * LookupTable.lookupPixle.
+ */
}
}
- else if (lut.getNumComponents() != 1
- &&
- lut.getNumComponents() != src.getColorModel().getNumComponents())
- throw new IllegalArgumentException("LookupOp.filter: "
- + "Incompatible lookup "
- + "table and source image");
-
+ else
+ {
// No alpha to ignore
int[] dbuf = new int[src.getColorModel().getNumComponents()];
@@ -132,16 +164,10 @@
for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf));
+ }
if (tgt != dst)
- {
- // Convert between color models.
- // TODO Check that premultiplied alpha is handled correctly here.
- Graphics2D gg = dst.createGraphics();
- gg.setRenderingHints(hints);
- gg.drawImage(tgt, 0, 0, null);
- gg.dispose();
- }
+ new ColorConvertOp(hints).filter(tgt, dst);
return dst;
}
@@ -160,18 +186,27 @@
public BufferedImage createCompatibleDestImage(BufferedImage src,
ColorModel dstCM)
{
- // FIXME: set properties to those in src
+ if (dstCM != null)
return new BufferedImage(dstCM,
src.getRaster().createCompatibleWritableRaster(),
- src.isPremultiplied, null);
+ src.isAlphaPremultiplied(), null);
+
+ // This is a strange exception, done for compatibility with the reference
+ // (as demonstrated by a mauve testcase)
+ int imgType = src.getType();
+ if (imgType == BufferedImage.TYPE_USHORT_GRAY)
+ imgType = BufferedImage.TYPE_BYTE_GRAY;
+
+ return new BufferedImage(src.getWidth(), src.getHeight(), imgType);
}
- /** Return corresponding destination point for source point.
+ /**
+ * Returns the corresponding destination point for a given source point.
*
- * LookupOp will return the value of src unchanged.
+ * This Op will return the source point unchanged.
+ *
* @param src The source point.
* @param dst The destination point.
- * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
*/
public final Point2D getPoint2D(Point2D src, Point2D dst)
{
@@ -182,7 +217,11 @@
return dst;
}
- /** Return the LookupTable for this op. */
+ /**
+ * Return the LookupTable for this op.
+ *
+ * @return The lookup table.
+ */
public final LookupTable getTable()
{
return lut;
@@ -196,7 +235,8 @@
return hints;
}
- /** Filter a raster through a lookup table.
+ /**
+ * Filter a raster through a lookup table.
*
* Applies the lookup table for this Rasterop to each pixel of src and
* puts the results in dest. If dest is null, a new Raster is created and
@@ -207,7 +247,8 @@
* @return The WritableRaster with the filtered pixels.
* @throws IllegalArgumentException if lookup ta...
[truncated message content] |