summaryrefslogtreecommitdiff
path: root/gnu/java
diff options
context:
space:
mode:
authorMario Torre <neugens@limasoftware.net>2008-06-15 18:14:54 +0000
committerMario Torre <neugens@limasoftware.net>2008-06-15 18:14:54 +0000
commit7e19ed027af34eb66eb263878bc802e6ec789818 (patch)
tree6f5ade303e1041e3e8ccc36ea7b3c65ae01d4b98 /gnu/java
parent0dcbe3d84713c04ba9cff7ed0974286ee7a5f64e (diff)
downloadclasspath-7e19ed027af34eb66eb263878bc802e6ec789818.tar.gz
2008-06-15 Mario Torre <neugens@aicas.com>
* gnu/java/awt/java2d/AbstractGraphics2D.java (setColor): delegate to setPaint. (setPaint): fix to set paint context and foreground color. (imageCache): new field. (drawImage): new codepath for scaling images. (prepareImage): new method. (getPaintContext): set paintContext appropriately. * gnu/java/awt/java2d/RasterGraphics.java (renderScanline): new method, override from superclass to detect correct value of y while rendering the scanline. * gnu/java/awt/java2d/ScanlineConverter.java (renderShape): revert previous patch. * gnu/java/awt/peer/x/XEventPump.java (findMouseEventTarget): new method. (handleButtonPress): use of findMouseEventTarget to detect the correct target. (handleButtonRelease): likewise. * gnu/java/awt/peer/x/XGraphics2D.java (rawDrawImage): clip the target image so that it is completely contained in the destination pixmaps, as per X11 specification. * gnu/java/awt/peer/x/XToolkit.java (createTextField): method implemented. (createButton): likewise. (prepareImage): likewise. (createLabel): likewise. (checkImage): likewise. (createTextArea): likewise. (createCheckbox): likewise. (checkHeadLess): new method. * gnu/javax/imageio/bmp/BMPImageWriter.java (write): don't close the stream. * gnu/javax/imageio/bmp/BMPImageWriterSpi.java (names): added new names to the list of known names for BMP. * java/awt/image/WritableRaster.java (createWritableTranslatedChild): * javax/imageio/ImageIO.java (write): call dispose on ImageWriter after writing of the image.
Diffstat (limited to 'gnu/java')
-rw-r--r--gnu/java/awt/java2d/AbstractGraphics2D.java128
-rw-r--r--gnu/java/awt/java2d/RasterGraphics.java12
-rw-r--r--gnu/java/awt/java2d/ScanlineConverter.java3
-rw-r--r--gnu/java/awt/peer/x/GLGraphics.java1
-rw-r--r--gnu/java/awt/peer/x/XEventPump.java63
-rw-r--r--gnu/java/awt/peer/x/XGraphics2D.java20
-rw-r--r--gnu/java/awt/peer/x/XToolkit.java50
7 files changed, 227 insertions, 50 deletions
diff --git a/gnu/java/awt/java2d/AbstractGraphics2D.java b/gnu/java/awt/java2d/AbstractGraphics2D.java
index 52a9433c5..850465938 100644
--- a/gnu/java/awt/java2d/AbstractGraphics2D.java
+++ b/gnu/java/awt/java2d/AbstractGraphics2D.java
@@ -46,6 +46,7 @@ import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.CompositeContext;
+import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
@@ -75,9 +76,12 @@ import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
+import java.awt.image.FilteredImageSource;
import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
+import java.awt.image.ReplicateScaleFilter;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.RenderableImage;
@@ -86,6 +90,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.WeakHashMap;
/**
* This is a 100% Java implementation of the Java2D rendering pipeline. It is
@@ -154,7 +159,14 @@ public abstract class AbstractGraphics2D
extends Graphics2D
implements Cloneable, Pixelizer
{
-
+ /**
+ * Caches scaled versions of an image.
+ *
+ * @see #drawImage(Image, int, int, int, int, ImageObserver)
+ */
+ protected static final WeakHashMap<Image, HashMap<Dimension,Image>> imageCache =
+ new WeakHashMap<Image, HashMap<Dimension, Image>>();
+
/**
* Wether we use anti aliasing for rendering text by default or not.
*/
@@ -636,14 +648,29 @@ public abstract class AbstractGraphics2D
if (p != null)
{
paint = p;
-
+
if (! (paint instanceof Color))
- isOptimized = false;
+ {
+ isOptimized = false;
+ }
else
{
+ this.foreground = (Color) paint;
+ isForegroundColorNull = false;
updateOptimization();
}
}
+ else
+ {
+ this.foreground = Color.BLACK;
+ isForegroundColorNull = true;
+ }
+
+ // free resources if needed, then put the paint context to null
+ if (this.paintContext != null)
+ this.paintContext.dispose();
+
+ this.paintContext = null;
}
/**
@@ -1080,23 +1107,8 @@ public abstract class AbstractGraphics2D
* @param color the foreground to set
*/
public void setColor(Color color)
- {
- if (color == null)
- {
- this.foreground = Color.BLACK;
- isForegroundColorNull = true;
- }
- else
- {
- this.foreground = color;
- isForegroundColorNull = false;
- }
-
- // free resources if needed, then put the paint context to null
- if (this.paintContext != null)
- this.paintContext.dispose();
-
- this.paintContext = null;
+ {
+ this.setPaint(color);
}
public void setPaintMode()
@@ -1493,11 +1505,19 @@ public abstract class AbstractGraphics2D
ImageObserver observer)
{
AffineTransform t = new AffineTransform();
- t.translate(x, y);
- double scaleX = (double) width / (double) image.getWidth(observer);
- double scaleY = (double) height / (double) image.getHeight(observer);
- t.scale(scaleX, scaleY);
- return drawImage(image, t, observer);
+ int imWidth = image.getWidth(observer);
+ int imHeight = image.getHeight(observer);
+ if (imWidth == width && imHeight == height)
+ {
+ // No need to scale, fall back to non-scaling loops.
+ return drawImage(image, x, y, observer);
+ }
+ else
+ {
+ Image scaled = prepareImage(image, width, height);
+ // Ideally, this should notify the observer about the scaling progress.
+ return drawImage(scaled, x, y, observer);
+ }
}
/**
@@ -2015,16 +2035,60 @@ public abstract class AbstractGraphics2D
{
if (this.paintContext == null)
{
- return this.foreground.createContext(getColorModel(),
- getDeviceBounds(),
- getClipBounds(),
- getTransform(),
- getRenderingHints());
+ this.paintContext =
+ this.foreground.createContext(getColorModel(),
+ getDeviceBounds(),
+ getClipBounds(),
+ getTransform(),
+ getRenderingHints());
}
- else
+
+ return this.paintContext;
+ }
+
+ /**
+ * Scales an image to the specified width and height. This should also
+ * be used to implement
+ * {@link Toolkit#prepareImage(Image, int, int, ImageObserver)}.
+ * This uses {@link Toolkit#createImage(ImageProducer)} to create the actual
+ * image.
+ *
+ * @param image the image to prepare
+ * @param w the width
+ * @param h the height
+ *
+ * @return the scaled image
+ */
+ public static Image prepareImage(Image image, int w, int h)
+ {
+ // Try to find cached scaled image.
+ HashMap<Dimension,Image> scaledTable = imageCache.get(image);
+ Dimension size = new Dimension(w, h);
+ Image scaled = null;
+ if (scaledTable != null)
+ {
+ scaled = scaledTable.get(size);
+ }
+ if (scaled == null)
{
- return this.paintContext;
+ // No cached scaled image. Start scaling image now.
+ ImageProducer source = image.getSource();
+ ReplicateScaleFilter scaler = new ReplicateScaleFilter(w, h);
+ FilteredImageSource filteredSource =
+ new FilteredImageSource(source, scaler);
+ // Ideally, this should asynchronously scale the image.
+ Image scaledImage =
+ Toolkit.getDefaultToolkit().createImage(filteredSource);
+ scaled = scaledImage;
+ // Put scaled image in cache.
+ if (scaledTable == null)
+ {
+ scaledTable = new HashMap<Dimension,Image>();
+ imageCache.put(image, scaledTable);
+ }
+ scaledTable.put(size, scaledImage);
}
+ return scaled;
}
}
diff --git a/gnu/java/awt/java2d/RasterGraphics.java b/gnu/java/awt/java2d/RasterGraphics.java
index 013782204..61824d352 100644
--- a/gnu/java/awt/java2d/RasterGraphics.java
+++ b/gnu/java/awt/java2d/RasterGraphics.java
@@ -38,6 +38,9 @@ exception statement from your version. */
package gnu.java.awt.java2d;
+import gnu.x11.image.ZPixmap;
+
+import java.awt.Color;
import java.awt.GraphicsConfiguration;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
@@ -72,6 +75,15 @@ public class RasterGraphics
init();
}
+ @Override
+ public void renderScanline(int y, ScanlineCoverage c)
+ {
+ if (y >= getDeviceBounds().width)
+ return;
+
+ super.renderScanline(y, c);
+ }
+
/**
* Returns the color model of this Graphics object.
*
diff --git a/gnu/java/awt/java2d/ScanlineConverter.java b/gnu/java/awt/java2d/ScanlineConverter.java
index ac27cc18d..b00a15c16 100644
--- a/gnu/java/awt/java2d/ScanlineConverter.java
+++ b/gnu/java/awt/java2d/ScanlineConverter.java
@@ -206,7 +206,8 @@ public final class ScanlineConverter
// Ok, now we can perform the actual scanlining.
int realY = Fixed.intValue(FIXED_DIGITS, y + resolution);
boolean push = lastRealY != realY;
- doScanline(p, realY, push, haveClip);
+
+ doScanline(p, y, push, haveClip);
// Remove obsolete active edges.
//activeEdges.remove(y + halfStep);
diff --git a/gnu/java/awt/peer/x/GLGraphics.java b/gnu/java/awt/peer/x/GLGraphics.java
index 8fae5ee7e..dde5b9195 100644
--- a/gnu/java/awt/peer/x/GLGraphics.java
+++ b/gnu/java/awt/peer/x/GLGraphics.java
@@ -72,6 +72,7 @@ public class GLGraphics extends AbstractGraphics2D
public void setBackground(Color b)
{
super.setBackground(b);
+
gl.clearColor(b.getRed() / 255.F, b.getGreen() / 255.F,
b.getBlue() / 255.F, b.getAlpha() / 255.F);
}
diff --git a/gnu/java/awt/peer/x/XEventPump.java b/gnu/java/awt/peer/x/XEventPump.java
index 9db36b51d..379839196 100644
--- a/gnu/java/awt/peer/x/XEventPump.java
+++ b/gnu/java/awt/peer/x/XEventPump.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package gnu.java.awt.peer.x;
import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
@@ -170,7 +172,14 @@ public class XEventPump
button = 0;
drag = button;
- MouseEvent mp = new MouseEvent(awtWindow, MouseEvent.MOUSE_PRESSED,
+ Component target =
+ findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
+ if(target == null)
+ {
+ target = awtWindow;
+ }
+
+ MouseEvent mp = new MouseEvent(target, MouseEvent.MOUSE_PRESSED,
System.currentTimeMillis(),
KeyboardMapping.mapModifiers(event.getState())
| buttonToModifier(button),
@@ -191,7 +200,14 @@ public class XEventPump
button = 0;
drag = -1;
- MouseEvent mr = new MouseEvent(awtWindow, MouseEvent.MOUSE_RELEASED,
+ Component target =
+ findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
+ if(target == null)
+ {
+ target = awtWindow;
+ }
+
+ MouseEvent mr = new MouseEvent(target, MouseEvent.MOUSE_RELEASED,
System.currentTimeMillis(),
KeyboardMapping.mapModifiers(event.getState())
| buttonToModifier(button),
@@ -200,6 +216,7 @@ public class XEventPump
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mr);
}
+
private void handleMotionNotify(MotionNotify event)
{
Integer key = new Integer(event.getEventWindowID());
@@ -423,5 +440,47 @@ public class XEventPump
return 0;
}
+
+ /**
+ * Finds the heavyweight mouse event target.
+ *
+ * @param src the original source of the event
+ *
+ * @param pt the event coordinates
+ *
+ * @return the real mouse event target
+ */
+ private Component findMouseEventTarget(Component src, int x, int y)
+ {
+ Component found = null;
+ if (src instanceof Container)
+ {
+ Container cont = (Container) src;
+ int numChildren = cont.getComponentCount();
+ for (int i = 0; i < numChildren && found == null; i++)
+ {
+ Component child = cont.getComponent(i);
+ if (child != null && child.isVisible()
+ && child.contains(x - child.getX(), y - child.getY()))
+ {
+ if (child instanceof Container)
+ {
+ Component deeper = findMouseEventTarget(child,
+ x - child.getX(),
+ y - child.getY());
+ if (deeper != null)
+ found = deeper;
+ }
+ else if (! child.isLightweight())
+ found = child;
+ }
+ }
+ }
+ // Consider the source itself.
+ if (found == null && src.contains(x, y) && ! src.isLightweight())
+ found = src;
+
+ return found;
+ }
}
diff --git a/gnu/java/awt/peer/x/XGraphics2D.java b/gnu/java/awt/peer/x/XGraphics2D.java
index 68a176f21..0339a424d 100644
--- a/gnu/java/awt/peer/x/XGraphics2D.java
+++ b/gnu/java/awt/peer/x/XGraphics2D.java
@@ -394,9 +394,23 @@ public class XGraphics2D
xdrawable.put_image(xgc, zpixmap, x, y);
imageCache.put(image, zpixmap);
} else {
- ZPixmap zpixmap = (ZPixmap) xdrawable.image(x, y, w, h,
- 0xffffffff,
- gnu.x11.image.Image.Format.ZPIXMAP);
+
+ // TODO optimize reusing the rectangles
+ Rectangle source =
+ new Rectangle(0, 0, xdrawable.width, xdrawable.height);
+ Rectangle target = new Rectangle(x, y, w, h);
+
+ Rectangle destination = source.intersection(target);
+
+ x = destination.x;
+ y = destination.y;
+ w = destination.width;
+ h = destination.height;
+
+ ZPixmap zpixmap =
+ (ZPixmap) xdrawable.image(x, y, w, h,
+ 0xffffffff,
+ gnu.x11.image.Image.Format.ZPIXMAP);
for (int yy = 0; yy < h; yy++)
{
for (int xx = 0; xx < w; xx++)
diff --git a/gnu/java/awt/peer/x/XToolkit.java b/gnu/java/awt/peer/x/XToolkit.java
index c1724aad5..af12574a1 100644
--- a/gnu/java/awt/peer/x/XToolkit.java
+++ b/gnu/java/awt/peer/x/XToolkit.java
@@ -54,6 +54,7 @@ import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Label;
import java.awt.List;
@@ -120,11 +121,16 @@ import gnu.java.awt.ClasspathToolkit;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.font.OpenTypeFontPeer;
import gnu.java.awt.image.ImageConverter;
+import gnu.java.awt.java2d.AbstractGraphics2D;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
+import gnu.java.awt.peer.swing.SwingButtonPeer;
import gnu.java.awt.peer.swing.SwingCanvasPeer;
+import gnu.java.awt.peer.swing.SwingCheckboxPeer;
import gnu.java.awt.peer.swing.SwingLabelPeer;
import gnu.java.awt.peer.swing.SwingPanelPeer;
+import gnu.java.awt.peer.swing.SwingTextAreaPeer;
+import gnu.java.awt.peer.swing.SwingTextFieldPeer;
public class XToolkit
extends ClasspathToolkit
@@ -232,18 +238,24 @@ public class XToolkit
protected ButtonPeer createButton(Button target)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ checkHeadLess("No ButtonPeer can be created in an headless" +
+ "graphics environment.");
+
+ return new SwingButtonPeer(target);
}
protected TextFieldPeer createTextField(TextField target)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ checkHeadLess("No TextFieldPeer can be created in an headless " +
+ "graphics environment.");
+
+ return new SwingTextFieldPeer(target);
}
protected LabelPeer createLabel(Label target)
{
+ checkHeadLess("No LabelPeer can be created in an headless graphics " +
+ "environment.");
return new SwingLabelPeer(target);
}
@@ -255,8 +267,10 @@ public class XToolkit
protected CheckboxPeer createCheckbox(Checkbox target)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ checkHeadLess("No CheckboxPeer can be created in an headless graphics " +
+ "environment.");
+
+ return new SwingCheckboxPeer(target);
}
protected ScrollbarPeer createScrollbar(Scrollbar target)
@@ -273,8 +287,10 @@ public class XToolkit
protected TextAreaPeer createTextArea(TextArea target)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ checkHeadLess("No TextAreaPeer can be created in an headless graphics " +
+ "environment.");
+
+ return new SwingTextAreaPeer(target);
}
protected ChoicePeer createChoice(Choice target)
@@ -514,14 +530,14 @@ public class XToolkit
public boolean prepareImage(Image image, int width, int height, ImageObserver observer)
{
- // Images are loaded synchronously, so we don't bother and return true.
- return true;
+ Image scaled = AbstractGraphics2D.prepareImage(image, width, height);
+ return checkImage(image, width, height, observer) == ImageObserver.ALLBITS;
}
public int checkImage(Image image, int width, int height, ImageObserver observer)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ // Images are loaded synchronously, so we don't bother and return true.
+ return ImageObserver.ALLBITS;
}
public Image createImage(ImageProducer producer)
@@ -638,4 +654,14 @@ public class XToolkit
return false;
}
+ private void checkHeadLess(String message) throws HeadlessException
+ {
+ if(GraphicsEnvironment.isHeadless())
+ {
+ if(message == null)
+ message = "This method cannot be called in headless mode.";
+
+ throw new HeadlessException(message);
+ }
+ }
}