One of 3 patches, i wish we could already use hg with the record extension...
This patch fixes a few problems in AbstractGraphics2D and RasterGraphics (which is not fully working yet anyway, but at least we avoid some nasty exceptions). Also, I'm syncing the image scaler code for escher that Roman wrote in Jamaica. The full changelog for all the patchset follows. Thanks, Mario 2008-06-15 Mario Torre <[EMAIL PROTECTED]> * 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. -- Mario Torre, Software Developer, http://www.jroller.com/neugens/ aicas Allerton Interworks Computer Automated Systems GmbH Haid-und-Neu-Straße 18 * D-76131 Karlsruhe * Germany http://www.aicas.com * Tel: +49-721-663 968-53 pgp key: http://subkeys.pgp.net/ PGP Key ID: 80F240CF Fingerprint: BA39 9666 94EC 8B73 27FA FC7C 4086 63E3 80F2 40CF USt-Id: DE216375633, Handelsregister HRB 109481, AG Mannheim Geschäftsführer: Dr. James J. Hunt Please, support open standards: http://opendocumentfellowship.org/petition/ http://www.nosoftwarepatents.com/
### Eclipse Workspace Patch 1.0 #P classpath Index: gnu/java/awt/java2d/AbstractGraphics2D.java =================================================================== RCS file: /sources/classpath/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java,v retrieving revision 1.22 diff -u -r1.22 AbstractGraphics2D.java --- gnu/java/awt/java2d/AbstractGraphics2D.java 1 Jun 2008 12:01:14 -0000 1.22 +++ gnu/java/awt/java2d/AbstractGraphics2D.java 15 Jun 2008 17:54:00 -0000 @@ -46,6 +46,7 @@ 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.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.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 @@ 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 @@ 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 @@ * @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 @@ 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 @@ { 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; + + return this.paintContext; + } + + /** + * Scales an image to the specified width and height. This should also + * be used to implement + * [EMAIL PROTECTED] Toolkit#prepareImage(Image, int, int, ImageObserver)}. + * This uses [EMAIL PROTECTED] 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) + { + // 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; } } Index: gnu/java/awt/java2d/ScanlineConverter.java =================================================================== RCS file: /sources/classpath/classpath/gnu/java/awt/java2d/ScanlineConverter.java,v retrieving revision 1.7 diff -u -r1.7 ScanlineConverter.java --- gnu/java/awt/java2d/ScanlineConverter.java 29 May 2008 16:41:39 -0000 1.7 +++ gnu/java/awt/java2d/ScanlineConverter.java 15 Jun 2008 17:54:00 -0000 @@ -206,7 +206,8 @@ // 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); Index: gnu/java/awt/java2d/RasterGraphics.java =================================================================== RCS file: /sources/classpath/classpath/gnu/java/awt/java2d/RasterGraphics.java,v retrieving revision 1.4 diff -u -r1.4 RasterGraphics.java --- gnu/java/awt/java2d/RasterGraphics.java 29 May 2008 16:41:39 -0000 1.4 +++ gnu/java/awt/java2d/RasterGraphics.java 15 Jun 2008 17:54:00 -0000 @@ -38,6 +38,9 @@ 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 @@ 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. * Index: gnu/java/awt/peer/x/XEventPump.java =================================================================== RCS file: /sources/classpath/classpath/gnu/java/awt/peer/x/XEventPump.java,v retrieving revision 1.11 diff -u -r1.11 XEventPump.java --- gnu/java/awt/peer/x/XEventPump.java 19 May 2008 14:16:18 -0000 1.11 +++ gnu/java/awt/peer/x/XEventPump.java 15 Jun 2008 17:54:01 -0000 @@ -39,6 +39,8 @@ 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 @@ 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 @@ 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 @@ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mr); } + private void handleMotionNotify(MotionNotify event) { Integer key = new Integer(event.getEventWindowID()); @@ -423,5 +440,47 @@ 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; + } } Index: gnu/java/awt/peer/x/XToolkit.java =================================================================== RCS file: /sources/classpath/classpath/gnu/java/awt/peer/x/XToolkit.java,v retrieving revision 1.10 diff -u -r1.10 XToolkit.java --- gnu/java/awt/peer/x/XToolkit.java 18 Feb 2008 19:45:48 -0000 1.10 +++ gnu/java/awt/peer/x/XToolkit.java 15 Jun 2008 17:54:01 -0000 @@ -54,6 +54,7 @@ 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.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 @@ 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 @@ 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 @@ 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 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 @@ 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); + } + } } Index: gnu/java/awt/peer/x/GLGraphics.java =================================================================== RCS file: /sources/classpath/classpath/gnu/java/awt/peer/x/GLGraphics.java,v retrieving revision 1.2 diff -u -r1.2 GLGraphics.java --- gnu/java/awt/peer/x/GLGraphics.java 29 May 2008 16:41:39 -0000 1.2 +++ gnu/java/awt/peer/x/GLGraphics.java 15 Jun 2008 17:54:00 -0000 @@ -72,6 +72,7 @@ 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); }