diff options
author | Mario Torre <neugens@limasoftware.net> | 2008-06-15 18:14:54 +0000 |
---|---|---|
committer | Mario Torre <neugens@limasoftware.net> | 2008-06-15 18:14:54 +0000 |
commit | 7e19ed027af34eb66eb263878bc802e6ec789818 (patch) | |
tree | 6f5ade303e1041e3e8ccc36ea7b3c65ae01d4b98 /gnu/java | |
parent | 0dcbe3d84713c04ba9cff7ed0974286ee7a5f64e (diff) | |
download | classpath-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.java | 128 | ||||
-rw-r--r-- | gnu/java/awt/java2d/RasterGraphics.java | 12 | ||||
-rw-r--r-- | gnu/java/awt/java2d/ScanlineConverter.java | 3 | ||||
-rw-r--r-- | gnu/java/awt/peer/x/GLGraphics.java | 1 | ||||
-rw-r--r-- | gnu/java/awt/peer/x/XEventPump.java | 63 | ||||
-rw-r--r-- | gnu/java/awt/peer/x/XGraphics2D.java | 20 | ||||
-rw-r--r-- | gnu/java/awt/peer/x/XToolkit.java | 50 |
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); + } + } } |