From f06a83c0b2f7761510836194a6c9a8a72000937c Mon Sep 17 00:00:00 2001 From: Matthias Klose Date: Sat, 4 Aug 2007 10:53:49 +0000 Subject: Import GNU Classpath (libgcj-import-20070727). libjava/ 2007-08-04 Matthias Klose Import GNU Classpath (libgcj-import-20070727). * Regenerate class and header files. * Regenerate auto* files. * include/jvm.h: * jni-libjvm.cc (Jv_JNI_InvokeFunctions): Rename type. * jni.cc (_Jv_JNIFunctions, _Jv_JNI_InvokeFunctions): Likewise. * jni.cc (_Jv_JNI_CallAnyMethodA, _Jv_JNI_CallAnyVoidMethodA, _Jv_JNI_CallMethodA, _Jv_JNI_CallVoidMethodA, _Jv_JNI_CallStaticMethodA, _Jv_JNI_CallStaticVoidMethodA, _Jv_JNI_NewObjectA, _Jv_JNI_SetPrimitiveArrayRegion): Constify jvalue parameter. * java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA): Likewise. * java/lang/VMFloat.java (toString, parseFloat): New. * gnu/awt/xlib/XToolkit.java (setAlwaysOnTop, isModalityTypeSupported, isModalExclusionTypeSupported): New (stub only). * gnu/awt/xlib/XCanvasPeer.java (requestFocus): Likewise. * gnu/awt/xlib/XFramePeer.java (updateMinimumSize, updateIconImages, updateFocusableWindowState, setModalBlocked, getBoundsPrivate, setAlwaysOnTop): Likewise. * gnu/awt/xlib/XFontPeer.java (canDisplay): Update signature. * scripts/makemake.tcl: Ignore gnu/javax/sound/sampled/gstreamer, ignore javax.sound.sampled.spi.MixerProvider, ignore .in files. * HACKING: Mention --enable-gstreamer-peer, removal of generated files. libjava/classpath/ 2007-08-04 Matthias Klose * java/util/EnumMap.java (clone): Add cast. From-SVN: r127204 --- .../classpath/gnu/java/awt/font/FontDelegate.java | 12 +- .../gnu/java/awt/font/opentype/OpenTypeFont.java | 12 +- .../gnu/java/awt/java2d/AbstractGraphics2D.java | 172 ++--- .../classpath/gnu/java/awt/java2d/Pixelizer.java | 56 ++ .../gnu/java/awt/java2d/ScanlineConverter.java | 107 ++- .../gnu/java/awt/java2d/ScanlineCoverage.java | 630 ++++++++++++++++ .../classpath/gnu/java/awt/java2d/ShapeCache.java | 5 + .../gnu/java/awt/peer/ClasspathFontPeer.java | 2 +- .../gnu/java/awt/peer/GLightweightPeer.java | 9 + .../gnu/java/awt/peer/gtk/CairoGraphics2D.java | 5 +- .../gnu/java/awt/peer/gtk/ComponentGraphics.java | 2 +- .../gnu/java/awt/peer/gtk/FreetypeGlyphVector.java | 60 +- .../gnu/java/awt/peer/gtk/GdkFontPeer.java | 12 +- .../java/awt/peer/gtk/GdkGraphicsEnvironment.java | 17 +- .../gnu/java/awt/peer/gtk/GdkPixbufDecoder.java | 10 + .../gnu/java/awt/peer/gtk/GdkRobotPeer.java | 5 + .../java/awt/peer/gtk/GdkScreenGraphicsDevice.java | 18 +- .../gnu/java/awt/peer/gtk/GtkComponentPeer.java | 23 +- .../gnu/java/awt/peer/gtk/GtkFramePeer.java | 7 + .../gnu/java/awt/peer/gtk/GtkGenericPeer.java | 36 + .../gnu/java/awt/peer/gtk/GtkToolkit.java | 44 +- .../gnu/java/awt/peer/gtk/GtkWindowPeer.java | 25 + .../java/awt/peer/gtk/VolatileImageGraphics.java | 12 +- .../java/awt/peer/headless/HeadlessToolkit.java | 14 + .../gnu/java/awt/peer/qt/QtComponentPeer.java | 10 + .../gnu/java/awt/peer/qt/QtFontMetrics.java | 2 +- .../classpath/gnu/java/awt/peer/qt/QtFontPeer.java | 2 +- .../gnu/java/awt/peer/qt/QtFramePeer.java | 6 + .../classpath/gnu/java/awt/peer/qt/QtToolkit.java | 15 + .../gnu/java/awt/peer/qt/QtWindowPeer.java | 25 + .../gnu/java/awt/peer/swing/SwingButtonPeer.java | 33 +- .../gnu/java/awt/peer/swing/SwingCheckboxPeer.java | 261 +++++++ .../gnu/java/awt/peer/swing/SwingComponent.java | 10 + .../java/awt/peer/swing/SwingComponentPeer.java | 118 +-- .../java/awt/peer/swing/SwingContainerPeer.java | 20 +- .../gnu/java/awt/peer/swing/SwingLabelPeer.java | 14 +- .../gnu/java/awt/peer/swing/SwingListPeer.java | 14 +- .../gnu/java/awt/peer/swing/SwingPanelPeer.java | 4 +- .../gnu/java/awt/peer/swing/SwingTextAreaPeer.java | 213 +++++- .../java/awt/peer/swing/SwingTextFieldPeer.java | 43 +- .../gnu/java/awt/peer/swing/SwingToolkit.java | 16 + .../gnu/java/awt/peer/swing/SwingWindowPeer.java | 25 + .../gnu/java/awt/peer/x/KeyboardMapping.java | 4 + .../gnu/java/awt/peer/x/PixmapVolatileImage.java | 185 +++++ .../classpath/gnu/java/awt/peer/x/XEventPump.java | 60 +- .../classpath/gnu/java/awt/peer/x/XFontPeer.java | 759 -------------------- .../classpath/gnu/java/awt/peer/x/XFontPeer2.java | 179 ++++- .../classpath/gnu/java/awt/peer/x/XFramePeer.java | 6 + .../classpath/gnu/java/awt/peer/x/XGraphics.java | 792 --------------------- .../classpath/gnu/java/awt/peer/x/XGraphics2D.java | 202 +++--- .../java/awt/peer/x/XGraphicsConfiguration.java | 65 +- .../gnu/java/awt/peer/x/XGraphicsDevice.java | 69 +- libjava/classpath/gnu/java/awt/peer/x/XImage.java | 2 +- .../gnu/java/awt/peer/x/XLightweightPeer.java | 56 -- .../classpath/gnu/java/awt/peer/x/XToolkit.java | 28 +- .../classpath/gnu/java/awt/peer/x/XWindowPeer.java | 23 +- .../gnu/java/awt/peer/x/ZPixmapDataBuffer.java | 62 ++ libjava/classpath/gnu/java/math/Fixed.java | 13 + .../classpath/gnu/java/net/loader/URLLoader.java | 3 +- .../classpath/gnu/java/nio/charset/ISO_8859_1.java | 8 +- libjava/classpath/gnu/java/security/Engine.java | 4 +- 61 files changed, 2627 insertions(+), 2019 deletions(-) create mode 100644 libjava/classpath/gnu/java/awt/java2d/Pixelizer.java create mode 100644 libjava/classpath/gnu/java/awt/java2d/ScanlineCoverage.java create mode 100755 libjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java create mode 100644 libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java delete mode 100644 libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java delete mode 100644 libjava/classpath/gnu/java/awt/peer/x/XGraphics.java delete mode 100644 libjava/classpath/gnu/java/awt/peer/x/XLightweightPeer.java create mode 100644 libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java (limited to 'libjava/classpath/gnu/java') diff --git a/libjava/classpath/gnu/java/awt/font/FontDelegate.java b/libjava/classpath/gnu/java/awt/font/FontDelegate.java index 030f9d3..a778733 100644 --- a/libjava/classpath/gnu/java/awt/font/FontDelegate.java +++ b/libjava/classpath/gnu/java/awt/font/FontDelegate.java @@ -115,8 +115,16 @@ public interface FontDelegate * Returns the number of glyphs in this font face. */ public int getNumGlyphs(); - - + + /** + * Returns the glyph code for the specified character. + * + * @param c the character to map + * + * @return the glyph code + */ + public int getGlyphIndex(int c); + /** * Returns the index of the glyph which gets displayed if the font * cannot map a Unicode code point to a glyph. Many fonts show this diff --git a/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java b/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java index a270ce7..6c2193b 100644 --- a/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java +++ b/libjava/classpath/gnu/java/awt/font/opentype/OpenTypeFont.java @@ -617,7 +617,17 @@ public final class OpenTypeFont return new GNUGlyphVector(this, font, frc, glyphs); } - + /** + * Returns the glyph code for the specified character. + * + * @param c the character to map + * + * @return the glyph code + */ + public int getGlyphIndex(int c) + { + return getCharGlyphMap().getGlyph(c); + } /** * Determines the advance width for a glyph. diff --git a/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java b/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java index f6c5ff0..15ec90d 100644 --- a/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java +++ b/libjava/classpath/gnu/java/awt/java2d/AbstractGraphics2D.java @@ -51,6 +51,7 @@ import java.awt.Graphics2D; import java.awt.Image; import java.awt.Paint; import java.awt.PaintContext; +import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.RenderingHints; @@ -75,10 +76,10 @@ import java.awt.image.DataBuffer; import java.awt.image.ImageObserver; import java.awt.image.Raster; import java.awt.image.RenderedImage; +import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.awt.image.renderable.RenderableImage; import java.text.AttributedCharacterIterator; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -147,7 +148,7 @@ import java.util.Map; */ public abstract class AbstractGraphics2D extends Graphics2D - implements Cloneable + implements Cloneable, Pixelizer { /** @@ -156,13 +157,6 @@ public abstract class AbstractGraphics2D private static final Font FONT = new Font("SansSerif", Font.PLAIN, 12); /** - * Accuracy of the sampling in the anti-aliasing shape filler. - * Lower values give more speed, while higher values give more quality. - * It is advisable to choose powers of two. - */ - private static final int AA_SAMPLING = 8; - - /** * Caches certain shapes to avoid massive creation of such Shapes in * the various draw* and fill* methods. */ @@ -227,17 +221,6 @@ public abstract class AbstractGraphics2D private WritableRaster destinationRaster; /** - * Stores the alpha values for a scanline in the anti-aliasing shape - * renderer. - */ - private transient int[] alpha; - - /** - * The edge table for the scanline conversion algorithms. - */ - private transient ArrayList[] edgeTable; - - /** * Indicates if certain graphics primitives can be rendered in an optimized * fashion. This will be the case if the following conditions are met: * - The transform may only be a translation, no rotation, shearing or @@ -931,8 +914,8 @@ public abstract class AbstractGraphics2D { // Initialize clip if not already present. if (clip == null) - clip = s; - + setClip(s); + // This is so common, let's optimize this. else if (clip instanceof Rectangle && s instanceof Rectangle) { @@ -1174,7 +1157,9 @@ public abstract class AbstractGraphics2D { if (isOptimized) { - rawDrawLine(x1, y1, x2, y2); + int tx = (int) transform.getTranslateX(); + int ty = (int) transform.getTranslateY(); + rawDrawLine(x1 + tx, y1 + ty, x2 + tx, y2 + ty); } else { @@ -1214,7 +1199,8 @@ public abstract class AbstractGraphics2D { if (isOptimized) { - rawFillRect(x, y, width, height); + rawFillRect(x + (int) transform.getTranslateX(), + y + (int) transform.getTranslateY(), width, height); } else { @@ -1352,8 +1338,16 @@ public abstract class AbstractGraphics2D public void drawPolyline(int[] xPoints, int[] yPoints, int npoints) { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); + ShapeCache sc = getShapeCache(); + if (sc.polyline == null) + sc.polyline = new GeneralPath(); + GeneralPath p = sc.polyline; + p.reset(); + if (npoints > 0) + p.moveTo(xPoints[0], yPoints[0]); + for (int i = 1; i < npoints; i++) + p.lineTo(xPoints[i], yPoints[i]); + fill(p); } /** @@ -1364,6 +1358,7 @@ public abstract class AbstractGraphics2D ShapeCache sc = getShapeCache(); if (sc.polygon == null) sc.polygon = new Polygon(); + sc.polygon.reset(); sc.polygon.xpoints = xPoints; sc.polygon.ypoints = yPoints; sc.polygon.npoints = npoints; @@ -1378,6 +1373,7 @@ public abstract class AbstractGraphics2D ShapeCache sc = getShapeCache(); if (sc.polygon == null) sc.polygon = new Polygon(); + sc.polygon.reset(); sc.polygon.xpoints = xPoints; sc.polygon.ypoints = yPoints; sc.polygon.npoints = npoints; @@ -1397,7 +1393,10 @@ public abstract class AbstractGraphics2D { boolean ret; if (isOptimized) - ret = rawDrawImage(image, x, y, observer); + { + ret = rawDrawImage(image, x + (int) transform.getTranslateX(), + y + (int) transform.getTranslateY(), observer); + } else { AffineTransform t = new AffineTransform(); @@ -1559,17 +1558,15 @@ public abstract class AbstractGraphics2D if (isFont) { Object v = renderingHints.get(RenderingHints.KEY_TEXT_ANTIALIASING); - // We default to antialiasing on for text as long as we have no - // good hinting implemented. - antialias = (v == RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - //|| v == RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); + // We default to antialiasing for text rendering. + antialias = (v == RenderingHints.VALUE_TEXT_ANTIALIAS_ON + || v == RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); } else { Object v = renderingHints.get(RenderingHints.KEY_ANTIALIASING); antialias = (v == RenderingHints.VALUE_ANTIALIAS_ON); } - ScanlineConverter sc = getScanlineConverter(); int resolution = 0; if (antialias) @@ -1577,7 +1574,7 @@ public abstract class AbstractGraphics2D // Adjust resolution according to rendering hints. resolution = 2; } - sc.renderShape(this, s, clip, transform, resolution); + sc.renderShape(this, s, clip, transform, resolution, renderingHints); } /** @@ -1609,12 +1606,20 @@ public abstract class AbstractGraphics2D */ protected void rawDrawLine(int x0, int y0, int x1, int y1) { - draw(new Line2D.Float(x0, y0, x1, y1)); + ShapeCache sc = getShapeCache(); + if (sc.line == null) + sc.line = new Line2D.Float(); + sc.line.setLine(x0, y0, x1, y1); + draw(sc.line); } protected void rawDrawRect(int x, int y, int w, int h) { - draw(new Rectangle(x, y, w, h)); + ShapeCache sc = getShapeCache(); + if (sc.rect == null) + sc.rect = new Rectangle(); + sc.rect.setBounds(x, y, w, h); + draw(sc.rect); } /** @@ -1662,7 +1667,11 @@ public abstract class AbstractGraphics2D */ protected void rawFillRect(int x, int y, int w, int h) { - fill(new Rectangle(x, y, w, h)); + ShapeCache sc = getShapeCache(); + if (sc.rect == null) + sc.rect = new Rectangle(); + sc.rect.setBounds(x, y, w, h); + fill(sc.rect); } /** @@ -1718,10 +1727,38 @@ public abstract class AbstractGraphics2D * @param x1 the right offset * @param y the scanline */ - protected void fillScanline(int x0, int x1, int y) + public void renderScanline(int y, ScanlineCoverage c) { PaintContext pCtx = paintContext; + int x0 = c.getMinX(); + int x1 = c.getMaxX(); Raster paintRaster = pCtx.getRaster(x0, y, x1 - x0, 1); + + // Do the anti aliasing thing. + float coverageAlpha = 0; + float maxCoverage = c.getMaxCoverage(); + ColorModel cm = pCtx.getColorModel(); + DataBuffer db = paintRaster.getDataBuffer(); + Point loc = new Point(paintRaster.getMinX(), paintRaster.getMinY()); + SampleModel sm = paintRaster.getSampleModel(); + WritableRaster writeRaster = Raster.createWritableRaster(sm, db, loc); + WritableRaster alphaRaster = cm.getAlphaRaster(writeRaster); + int pixel; + ScanlineCoverage.Iterator iter = c.iterate(); + while (iter.hasNext()) + { + ScanlineCoverage.Range range = iter.next(); + coverageAlpha = range.getCoverage() / maxCoverage; + if (coverageAlpha < 1.0) + { + for (int x = range.getXPos(); x < range.getXPosEnd(); x++) + { + pixel = alphaRaster.getSample(x, y, 0); + pixel = (int) (pixel * coverageAlpha); + alphaRaster.setSample(x, y, 0, pixel); + } + } + } ColorModel paintColorModel = pCtx.getColorModel(); CompositeContext cCtx = composite.createContext(paintColorModel, getColorModel(), @@ -1734,66 +1771,6 @@ public abstract class AbstractGraphics2D /** - * Fills a horizontal line between x0 and x1 for anti aliased rendering. - * the alpha array contains the deltas of the alpha values from one pixel - * to the next. - * - * @param alpha the alpha values in the scanline - * @param x0 the beginning of the scanline - * @param yy the y coordinate of the line - */ - private void fillScanlineAA(int[] alpha, int x0, int yy, int numPixels, - PaintContext pCtx, int offs) - { - CompositeContext cCtx = composite.createContext(pCtx.getColorModel(), - getColorModel(), - renderingHints); - Raster paintRaster = pCtx.getRaster(x0, yy, numPixels, 1); - //System.err.println("paintColorModel: " + pCtx.getColorModel()); - WritableRaster aaRaster = paintRaster.createCompatibleWritableRaster(); - ColorModel cm = pCtx.getColorModel(); - double lastAlpha = 0.; - int lastAlphaInt = 0; - - Object pixel = null; - int[] comps = null; - int x1 = x0 + numPixels; - for (int x = x0; x < x1; x++) - { - int i = x - offs; - if (alpha[i] != 0) - { - lastAlphaInt += alpha[i]; - lastAlpha = (double) lastAlphaInt / (double) AA_SAMPLING; - alpha[i] = 0; - } - pixel = paintRaster.getDataElements(x - x0, 0, pixel); - comps = cm.getComponents(pixel, comps, 0); - if (cm.hasAlpha() && ! cm.isAlphaPremultiplied()) - comps[comps.length - 1] *= lastAlpha; - else - { - int max; - if (cm.hasAlpha()) - max = comps.length - 2; - else - max = comps.length - 1; - for (int j = 0; j < max; j++) - comps[j] *= lastAlpha; - } - pixel = cm.getDataElements(comps, 0, pixel); - aaRaster.setDataElements(x - x0, 0, pixel); - } - - WritableRaster targetChild = - destinationRaster.createWritableTranslatedChild(-x0, -yy); - cCtx.compose(aaRaster, targetChild, targetChild); - updateRaster(destinationRaster, x0, yy, numPixels, 1); - - cCtx.dispose(); - } - - /** * Initializes this graphics object. This must be called by subclasses in * order to correctly initialize the state of this object. */ @@ -1971,4 +1948,5 @@ public abstract class AbstractGraphics2D } return sc; } + } diff --git a/libjava/classpath/gnu/java/awt/java2d/Pixelizer.java b/libjava/classpath/gnu/java/awt/java2d/Pixelizer.java new file mode 100644 index 0000000..43e53bf --- /dev/null +++ b/libjava/classpath/gnu/java/awt/java2d/Pixelizer.java @@ -0,0 +1,56 @@ +/* Pixelizer.java -- Interface for the target of the rasterizer + Copyright (C) 2007 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.java2d; + +/** + * A pixelizer is responsible for actually manipulating the pixel of a drawing + * surface after the scanline conversion process. It receives coverage + * information for a scanline and adjusts the surface pixels accordingly. + */ +public interface Pixelizer +{ + + /** + * Renders the pixel for one scanline at the Y location y + * and using the coverage information in sc. + * + * @param y the scanline Y coordinate + * @param sc the coverage information + */ + void renderScanline(int y, ScanlineCoverage sc); +} diff --git a/libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java b/libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java index 9f9d892..2693a0b 100644 --- a/libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java +++ b/libjava/classpath/gnu/java/awt/java2d/ScanlineConverter.java @@ -1,5 +1,5 @@ /* ScanlineConverter.java -- Rasterizes Shapes - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,6 +40,7 @@ package gnu.java.awt.java2d; import gnu.java.math.Fixed; +import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; @@ -47,7 +48,7 @@ import java.awt.geom.PathIterator; /** * Rasterizes {@link Shape} objects on an AbstractGraphics2D. */ -final class ScanlineConverter +public final class ScanlineConverter { /** @@ -56,11 +57,16 @@ final class ScanlineConverter private static int FIXED_DIGITS = 6; /** - * The fixed value for the number 1. + * The fixed point constant for the number one. */ private static int ONE = Fixed.fixedValue(FIXED_DIGITS, 1); /** + * The number of significant bits for the Y resolution. + */ + private static int Y_RESOLUTION = 4; + + /** * The actual number of scanlines. */ private int numScanlines; @@ -109,6 +115,13 @@ final class ScanlineConverter private int minY; private int maxY; + private int minX; + private int maxX; + + /** + * Holds and manages information about the pixel coverage. + */ + private ScanlineCoverage scanlineCoverage; /** * Create a new ScanlineConverter. @@ -120,18 +133,23 @@ final class ScanlineConverter activeEdges = new ActiveEdges(); edgePool = new PolyEdge(); edgePoolLast = edgePool; + scanlineCoverage = new ScanlineCoverage(); } /** * Renders the specified shape using the specified clip and transform. * + * @param p the pixelizer that receives the coverage information * @param shape the shape to render * @param clip the clip * @param trans the transform */ - void renderShape(AbstractGraphics2D g, Shape shape, Shape clip, - AffineTransform trans, int res) + public void renderShape(Pixelizer p, Shape shape, Shape clip, + AffineTransform trans, int res, RenderingHints hints) { + // TODO: Do something useful with the rendering hints. Like, adjusting + // the resolution. + // Prepare resolution and upper bounds. clear(); setResolution(res); @@ -139,11 +157,12 @@ final class ScanlineConverter boolean haveClip = clip != null; // Add shapes. - PathIterator path = shape.getPathIterator(trans, resolution); + float flatness = Fixed.floatValue(FIXED_DIGITS, resolution / 2); + PathIterator path = shape.getPathIterator(trans, flatness); addShape(path, false); if (haveClip) { - path= clip.getPathIterator(trans, resolution); + path= clip.getPathIterator(trans, flatness); addShape(path, true); } @@ -157,11 +176,11 @@ final class ScanlineConverter } int y = upperBounds; - int lastIndex = scanlineIndex(y - resolution); int index; activeEdges.clear(); // The render loop... Scanline scanline = null; + int lastRealY = Fixed.intValue(FIXED_DIGITS, y); while (y <= maxY) { // First we put together our list of active edges. @@ -184,15 +203,16 @@ final class ScanlineConverter activeEdges.intersectSortAndPack(FIXED_DIGITS, y + halfStep); // Ok, now we can perform the actual scanlining. - boolean push = lastIndex != index; - doScanline(g, y, push, haveClip); + int realY = Fixed.intValue(FIXED_DIGITS, y + resolution); + boolean push = lastRealY != realY; + doScanline(p, y, push, haveClip); // Remove obsolete active edges. //activeEdges.remove(y + halfStep); - // Go on with the next line... y += resolution; - lastIndex = index; + lastRealY = realY; + } } @@ -212,17 +232,31 @@ final class ScanlineConverter sl.clear(); } + // Reset scanline coverage. + scanlineCoverage.clear(); + // Reset bounds. minY = Integer.MAX_VALUE; maxY = Integer.MIN_VALUE; + minX = Integer.MAX_VALUE; + maxX = Integer.MIN_VALUE; } /** * Performs the scanlining on the current set of active edges. + * + * @param p the pixelizer to receive the pixel coverage data + * @param y the Y coordinate + * @param push true when the scanline is ready to be pushed to the + * pixelizer + * @param haveClip true when there's a clip, false otherwise */ - private void doScanline(AbstractGraphics2D g, int y, boolean push, + private void doScanline(Pixelizer p, int y, boolean push, boolean haveClip) { + // First, rewind the scanline coverage. + scanlineCoverage.rewind(); + // We begin outside the clip and outside the shape. We only draw when // we are inside the clip AND inside the shape. boolean inClip = ! haveClip; @@ -238,22 +272,16 @@ final class ScanlineConverter int x0 = lastEdge.xIntersection; int x1 = edge.xIntersection; assert x0 <= x1; - if (push) - { - if (resolution == ONE) - { - // Non-AA rendering. - g.fillScanline(Fixed.intValue(FIXED_DIGITS, x0), - Fixed.intValue(FIXED_DIGITS, x1 - resolution), - Fixed.intValue(FIXED_DIGITS, y)); - } - else - { - // AA rendering. - // FIXME: Implement. - System.err.println("Implement AA rendering."); - } - } + + int pix0 = Fixed.intValue(FIXED_DIGITS, x0); + int pix1 = Fixed.intValue(FIXED_DIGITS, x1); + int frac0 = ONE - Fixed.trunc(FIXED_DIGITS, x0); + int frac1 = ONE - Fixed.trunc(FIXED_DIGITS, x1); + // Only keep the first 4 digits after the point. + frac0 = frac0 >> (FIXED_DIGITS - Y_RESOLUTION); + frac1 = frac1 >> (FIXED_DIGITS - Y_RESOLUTION); + scanlineCoverage.add(pix0, 1 * (1 << Y_RESOLUTION), frac0); + scanlineCoverage.add(pix1, -1 * (1 << Y_RESOLUTION), -frac1); } if (edge.isClip) inClip = ! inClip; @@ -262,7 +290,15 @@ final class ScanlineConverter lastEdge = edge; } - } + + // Push out the whole scanline to the pixelizer. + if (push && ! scanlineCoverage.isEmpty()) + { + p.renderScanline(Fixed.intValue(FIXED_DIGITS, y), scanlineCoverage); + scanlineCoverage.clear(); + } + } + /** * Sets the resolution. A value of 0 rasterizes the shape normally without @@ -272,9 +308,12 @@ final class ScanlineConverter */ private void setResolution(int res) { + int scanlinesPerPixel = 1 << res; int one = Fixed.fixedValue(FIXED_DIGITS, 1); - resolution = one / (1 << res); + resolution = one / (scanlinesPerPixel); halfStep = resolution / 2; + + scanlineCoverage.setMaxCoverage(scanlinesPerPixel << Y_RESOLUTION); } /** @@ -309,6 +348,8 @@ final class ScanlineConverter startY = lastY = Fixed.fixedValue(FIXED_DIGITS, coords[1]); minY = Math.min(startY, minY); maxY = Math.max(startY, maxY); + minX = Math.min(startX, minX); + maxX = Math.max(startX, maxX); break; case PathIterator.SEG_LINETO: int x = Fixed.fixedValue(FIXED_DIGITS, coords[0]); @@ -318,6 +359,8 @@ final class ScanlineConverter lastY = y; minY = Math.min(lastY, minY); maxY = Math.max(lastY, maxY); + minX = Math.min(lastX, minX); + maxX = Math.max(lastX, maxX); break; case PathIterator.SEG_CLOSE: edgePoolAdd(lastX, lastY, startX, startY, clip); @@ -371,7 +414,7 @@ final class ScanlineConverter { int val1 = Fixed.div(FIXED_DIGITS, y, resolution); int rounded = Fixed.round(FIXED_DIGITS, val1); - return Fixed.div(FIXED_DIGITS, rounded, resolution); + return Fixed.mul(FIXED_DIGITS, rounded, resolution); } /** diff --git a/libjava/classpath/gnu/java/awt/java2d/ScanlineCoverage.java b/libjava/classpath/gnu/java/awt/java2d/ScanlineCoverage.java new file mode 100644 index 0000000..6db7fb0 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/java2d/ScanlineCoverage.java @@ -0,0 +1,630 @@ +/* ScanlineCoverage.java -- Manages coverage information for a scanline + Copyright (C) 2007 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.java2d; + +/** + * Stores and handles the pixel converage for a scanline. The pixel coverage + * is stored as sorted list of {@linke Covergage} entries, each of which holds + * information about the coverage for the X and Y axis. This is utilized to + * compute the actual coverage for each pixel on the scanline and finding + * chunks of pixels with equal coverage quickly. + */ +public final class ScanlineCoverage +{ + + /** + * Iterates over the coverage list and calculates the actual coverage + * ranges on a scanline. + */ + public final class Iterator + { + /** + * This instance is reused in the iteration. + */ + private Range range; + + /** + * The pointer to the current item in the iteration. + */ + private Coverage currentItem; + + /** + * The current coverage value. + */ + private int currentCoverage; + + /** + * True when the current pixel coverage has already been handled, false + * otherwise. + */ + private boolean handledPixelCoverage; + + /** + * Creates a new CoverageIterator. + */ + Iterator() + { + range = new Range(); + } + + /** + * Returns the next coverage range on the scanline. The returned object + * will always be the same object, but with different values. Keep that + * in mind when dealing with this object. + * + * @return the next coverage range on the scanline + */ + public Range next() + { + // TODO: Lump together the single-pixel coverage and the + // between-pixel coverage when the pixel coverage delta is 0. + if (handledPixelCoverage == false) + { + // Handle single pixel coverage. + range.setXPos(currentItem.xPos); + range.setLength(1); + range.setCoverage(currentCoverage + currentItem.pixelCoverage); + handledPixelCoverage = true; + } + else + { + // Handle pixel span coverage. + currentCoverage += currentItem.covDelta; + range.setCoverage(currentCoverage); + range.setXPos(currentItem.xPos + 1); + currentItem = currentItem.next; + range.setLength(currentItem.xPos - range.xPos); + handledPixelCoverage = false; + } + return range; + } + + /** + * Returns {@ true} when there are more coverage ranges to iterate, + * {@ false} otherwise. + * + * @return {@ true} when there are more coverage ranges to iterate, + * {@ false} otherwise + */ + public boolean hasNext() + { + boolean hasNext; + if (currentItem != null && handledPixelCoverage == false) + { + // We have at least one more coverage item when there's a pixel + // coverage piece left. + hasNext = true; + } + else if (currentItem == null || currentItem.next == null + || currentItem.next == last) + { + hasNext = false; + } + else + { + hasNext = true; + } + return hasNext; + } + + /** + * Resets this iterator to the start of the list. + */ + void reset() + { + currentItem = head; + currentCoverage = 0; + handledPixelCoverage = false; + } + } + + /** + * A data object that carries information about pixel coverage on a scanline. + * The data consists of a starting X position on the scanline, the + * length of the range in pixels and the actual coverage value. +ยด */ + public static final class Range + { + /** + * The X position on the scanline, in pixels. + */ + private int xPos; + + /** + * The length of the range, in pixels. + */ + private int length; + + /** + * The actual coverage. The relation depends on + * {@link ScanlineCoverage#maxCoverage}. + */ + private int coverage; + + /** + * Creates a new CoverageRange object. + */ + Range() + { + // Nothing to do. The values get initialized in the corresponding + // setters. + } + + /** + * Sets the X start position (left) on the scanline. This value is + * considered to be in pixels and device space. + * + * @param x the x position + */ + void setXPos(int x) + { + xPos = x; + } + + /** + * Returns the X start position (left) on the scanline. This value + * is considered to be in pixels and device space. + * + * @return the X position on the scanline + */ + public int getXPos() + { + return xPos; + } + + /** + * Sets the length of the pixel range. This is in pixel units. + * + * @param l the length of the range + */ + void setLength(int l) + { + length = l; + } + + /** + * Returns the length of the range in pixel units. + * + * @return the length of the range in pixel units + */ + public int getLength() + { + return length; + } + + /** + * Returns the first X position after the range. + * + * @return the first X position after the range + */ + public int getXPosEnd() + { + return xPos + length; + } + + /** + * Sets the coverage of the pixel range. The relation of that value + * depends on {@link ScanlineCoverage#maxCoverage}. + * + * @param cov the coverage value for the pixel range + */ + void setCoverage(int cov) + { + coverage = cov; + } + + /** + * Returns the coverage of the pixel range. The relation of this value + * depends on {@link ScanlineCoverage#getMaxCoverage()}. + * + * @return the coverage of the pixel range + */ + public int getCoverage() + { + return coverage; + } + + /** + * Returns a string representation. + */ + public String toString() + { + return "Coverage range: xPos=" + xPos + ", length=" + length + + ", coverage: " + coverage; + } + } + + /** + * One bucket in the list. + */ + private static final class Coverage + { + /** + * The X coordinate on the scanline to which this bucket belongs. + */ + int xPos; + + /** + * The coverage delta from the pixel at xPos to xPos + 1. + */ + int covDelta; + + /** + * The delta for the pixel at xPos. This is added to the pixel at xPos, + * but not to the following pixel. + */ + int pixelCoverage; + + /** + * Implements a linked list. This points to the next element of the list. + */ + Coverage next; + + /** + * Returns the X coordinate for this entry. + * + * @return the X coordinate for this entry + */ + public int getXPos() + { + return xPos; + } + + /** + * Returns the coverage delta for this entry. + * + * @return the coverage delta for this entry + */ + public int getCoverageDelta() + { + return covDelta; + } + + /** + * Returns a string representation. + * + * @return a string representation + */ + public String toString() + { + return "Coverage: xPos: " + xPos + ", covDelta: " + covDelta; + } + + /** + * Returns a string representation of this entry and all the following + * in the linked list. + * + * @return a string representation of this entry and all the following + * in the linked list + */ + public String list() + { + String str = toString(); + if (next != null) + str = str + " --> " + next.list(); + return str; + } + } + + /** + * The head of the sorted list of buckets. + */ + private Coverage head; + + /** + * The current bucket. We make use of the fact that the scanline converter + * always scans the scanline (and thus this list) from left to right to + * quickly find buckets or insertion points. + */ + private Coverage current; + + /** + * The item that is before current in the list. + */ + private Coverage currentPrev; + + /** + * The bucket after the last valid bucket. Unused buckets are not thrown + * away and garbage collected. Instead, we keep them at the tail of the list + * and reuse them when necessary. + */ + private Coverage last; + + /** + * The last valid entry. + */ + private Coverage lastPrev; + + /** + * The minimum X coordinate of this scanline. + */ + private int minX; + + /** + * The maximum X coordinate of this scanline. + */ + private int maxX; + + /** + * The maximum coverage value. + */ + private int maxCoverage; + + /** + * The iterator over the ranges of this scanline. + */ + private Iterator iterator; + + /** + * Creates a new ScanlineCoverage instance. + */ + public ScanlineCoverage() + { + iterator = new Iterator(); + } + + /** + * Indicates the the next scan of the scanline begins and that the next + * request will be at the beginning of this list. This makes searching and + * sorting of this list very quick. + */ + public void rewind() + { + current = head; + currentPrev = null; + } + + /** + * Clears the list. This does not throw away the old buckets but only + * resets the end-pointer of the list to the first element. All buckets are + * then unused and are reused when the list is filled again. + */ + public void clear() + { + last = head; + lastPrev = null; + current = head; + currentPrev = null; + minX = Integer.MAX_VALUE; + maxX = Integer.MIN_VALUE; + } + + /** + * This adds the specified coverage to the pixel at the specified + * X position. + * + * @param x the X position + * @param xc the x coverage + * @param yc the y coverage + */ + public void add(int x, int xc, int yc) + { + Coverage bucket = findOrInsert(x); + bucket.covDelta += xc; + bucket.pixelCoverage += yc; + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + } + + /** + * Returns the maximum coverage value for the scanline. + * + * @return the maximum coverage value for the scanline + */ + public int getMaxCoverage() + { + return maxCoverage; + } + + /** + * Sets the maximum coverage value for the scanline. + * + * @param maxCov the maximum coverage value for the scanline + */ + void setMaxCoverage(int maxCov) + { + maxCoverage = maxCov; + } + + /** + * Returns the maximum X coordinate of the current scanline. + * + * @return the maximum X coordinate of the current scanline + */ + public int getMaxX() + { + return maxX; + } + + /** + * Returns the minimum X coordinate of the current scanline. + * + * @return the minimum X coordinate of the current scanline + */ + public int getMinX() + { + return minX; + } + + /** + * Finds the bucket in the list with the specified X coordinate. + * If no such bucket is found, then a new one is fetched (either a cached + * bucket from the end of the list or a newly allocated one) inserted at the + * correct position and returned. + * + * @param x the X coordinate + * + * @return a bucket to hold the coverage data + */ + private Coverage findOrInsert(int x) + { + // First search for a matching bucket. + if (head == null) + { + // Special case: the list is still empty. + // Testpoint 1. + head = new Coverage(); + head.xPos = x; + current = head; + currentPrev = null; + return head; + } + + // This performs a linear search, starting from the current bucket. + // This is reasonably efficient because access to this list is always done + // in a linear fashion and we are usually not more then 1 or 2 buckets away + // from the one we're looking for. + Coverage match = current; + Coverage prev = currentPrev; + while (match != last && match.xPos < x) + { + prev = match; + match = match.next; + } + + // At this point we have either found an entry with xPos >= x, or reached + // the end of the list (match == last || match == null). + if (match == null) + { + // End of the list. No cached items to reuse. + // Testpoint 2. + match = new Coverage(); + match.xPos = x; + if (prev != null) + prev.next = match; + current = match; + currentPrev = prev; + return match; + } + else if (match == last) + { + // End of the list. Reuse this item. Expand list. + // Testpoint 3. + last = match.next; + lastPrev = match; + match.xPos = x; + match.covDelta = 0; + match.pixelCoverage = 0; + // Keep link to last element or null, indicating the end of the list. + current = match; + currentPrev = prev; + return match; + } + + if (x == match.xPos) + { + // Special case: We have another coverage entry at the same location + // as an already existing entry. Return this. + // Testpoint 4. + current = match; + currentPrev = prev; + return match; + } + else // x <= match.xPos + { + assert (x <= match.xPos); + assert (prev == null ||x > prev.xPos); + + // Create new entry, or reuse existing one. + Coverage cov; + if (last != null) + { + // Testpoint 5. + cov = last; + last = cov.next; + lastPrev.next = last; + } + else + { + // Testpoint 6. + cov = new Coverage(); + } + + cov.xPos = x; + cov.covDelta = 0; + cov.pixelCoverage = 0; + + // Insert this item in the list. + if (prev != null) + { + // Testpoint 5 & 6. + prev.next = cov; + cov.next = match; + current = cov; + currentPrev = prev; + } + else + { + // Testpoint 7. + assert (match == head); + // Insert at head. + head = cov; + head.next = match; + current = head; + currentPrev = null; + } + return cov; + } + } + + /** + * (Re-)Starts iterating the coverage values for the scanline. + * Use the returned iterator to get the consecutive coverage ranges. + * + * @return the iterator + */ + public Iterator iterate() + { + iterator.reset(); + return iterator; + } + + /** + * Returns {@ true} if this object has no entries for the current scanline, + * {@ false} otherwise. + * + * @return {@ true} if this object has no entries for the current scanline, + * {@ false} otherwise + */ + public boolean isEmpty() + { + return head == null || head == last + || head.next == null || head.next == last; + } + +} diff --git a/libjava/classpath/gnu/java/awt/java2d/ShapeCache.java b/libjava/classpath/gnu/java/awt/java2d/ShapeCache.java index 034b53c..89a9ac4 100644 --- a/libjava/classpath/gnu/java/awt/java2d/ShapeCache.java +++ b/libjava/classpath/gnu/java/awt/java2d/ShapeCache.java @@ -42,6 +42,7 @@ import java.awt.Polygon; import java.awt.Rectangle; import java.awt.geom.Arc2D; import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.RoundRectangle2D; @@ -82,4 +83,8 @@ public class ShapeCache */ public Polygon polygon; + /** + * A cached polyline. + */ + public GeneralPath polyline; } diff --git a/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java index 60fde25..e43e5f2 100644 --- a/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java @@ -644,7 +644,7 @@ public abstract class ClasspathFontPeer * be ignored. */ - public abstract boolean canDisplay (Font font, char c); + public abstract boolean canDisplay (Font font, int c); /** * Implementation of {@link Font#canDisplay(String)}, diff --git a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java index f9a7bac..bf40bf3 100644 --- a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java @@ -449,4 +449,13 @@ public class GLightweightPeer { // Nothing to do here for lightweights. } + + public boolean requestFocus(Component lightweightChild, boolean temporary, + boolean focusedWindowChangeAllowed, + long time, sun.awt.CausedFocusEvent.Cause cause) + { + // Always grant focus request. + return true; + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java index 3a38607..db8acd1 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java @@ -1726,7 +1726,8 @@ public abstract class CairoGraphics2D extends Graphics2D .equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)); ignoreAA = true; - if (gv instanceof FreetypeGlyphVector && alpha == 1.0) + if (gv instanceof FreetypeGlyphVector && alpha == 1.0 + && !((FreetypeGlyphVector)gv).hasTransforms()) { int n = gv.getNumGlyphs (); int[] codes = gv.getGlyphCodes (0, n, null); @@ -2164,4 +2165,4 @@ public abstract class CairoGraphics2D extends Graphics2D return new Rectangle2D.Double(minX, minY, (maxX - minX), (maxY - minY)); } -} +} \ No newline at end of file diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java index e543206..4ce20a3 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java @@ -938,4 +938,4 @@ public class ComponentGraphics extends CairoGraphics2D unlock(); } } -} +} \ No newline at end of file diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java index 280f3e6..8d6d01a 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java @@ -43,6 +43,8 @@ import java.awt.font.FontRenderContext; import java.awt.font.GlyphJustificationInfo; import java.awt.font.GlyphMetrics; import java.awt.font.GlyphVector; +import java.awt.font.TextAttribute; +import java.awt.font.TransformAttribute; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; @@ -86,7 +88,10 @@ public class FreetypeGlyphVector extends GlyphVector private long[] fontSet = null; /** - * Glyph transforms. (de facto only the translation is used) + * Glyph transforms. Supports all transform operations. + * + * The identity transform should not be stored in this array; use a null + * instead (will result in performance improvements). */ private AffineTransform[] glyphTransforms; @@ -185,9 +190,12 @@ public class FreetypeGlyphVector extends GlyphVector fontSet = new long[nGlyphs]; glyphPositions = new float[(nGlyphs + 1) * 2]; glyphTransforms = new AffineTransform[ nGlyphs ]; + Arrays.fill(glyphTransforms, null); + for(int i = 0; i < nGlyphs; i++ ) { - glyphTransforms[ i ] = new AffineTransform( gv.glyphTransforms[ i ] ); + if (gv.glyphTransforms[i] != null) + glyphTransforms[ i ] = new AffineTransform(gv.glyphTransforms[i]); glyphCodes[i] = gv.glyphCodes[ i ]; } System.arraycopy(gv.glyphPositions, 0, glyphPositions, 0, @@ -313,6 +321,25 @@ public class FreetypeGlyphVector extends GlyphVector } glyphPositions[nGlyphs * 2] = x; glyphPositions[nGlyphs * 2 + 1] = y; + + // Apply any transform that may be in the font's attributes + TransformAttribute ta; + ta = (TransformAttribute)font.getAttributes().get(TextAttribute.TRANSFORM); + if (ta != null) + { + AffineTransform tx = ta.getTransform(); + + // Transform glyph positions + tx.transform(glyphPositions, 0, glyphPositions, 0, + glyphPositions.length / 2); + + // Also store per-glyph scale/shear/rotate (but not translation) + double[] matrix = new double[4]; + tx.getMatrix(matrix); + AffineTransform deltaTx = new AffineTransform(matrix); + if (!deltaTx.isIdentity()) + Arrays.fill(glyphTransforms, deltaTx); + } } /** @@ -375,7 +402,7 @@ public class FreetypeGlyphVector extends GlyphVector p.getY() + r.getY() + r.getHeight()}; if (glyphTransforms[glyphIndex] != null) - glyphTransforms[glyphIndex].transform(bounds, 0, bounds, 0, 4); + glyphTransforms[glyphIndex].transform(bounds, 0, bounds, 0, 2); return new Rectangle2D.Double(bounds[0], bounds[1], bounds[2] - bounds[0], bounds[3] - bounds[1]); @@ -473,7 +500,19 @@ public class FreetypeGlyphVector extends GlyphVector { return glyphTransforms[glyphIndex]; } - + + /** + * Checks whether any transform has been set on any glyphs. + */ + protected boolean hasTransforms() + { + for (int i = 0; i < glyphTransforms.length; i++) + if (glyphTransforms[i] != null) + return true; + + return false; + } + /** * Returns the visual bounds of a glyph * May be off by a pixel or two due to hinting/rasterization. @@ -570,6 +609,19 @@ public class FreetypeGlyphVector extends GlyphVector */ public void setGlyphTransform(int glyphIndex, AffineTransform newTX) { + // The identity transform should never be in the glyphTransforms array; + // using and checking for nulls can be much faster. + if (newTX != null && newTX.isIdentity()) + newTX = null; + + // If the old and new transforms are identical, bail + if (glyphTransforms[glyphIndex] == null && newTX == null) + return; + + if (newTX != null && newTX.equals(glyphTransforms[glyphIndex])) + return; + + // Invalidate bounds cache and set new transform logicalBounds = null; glyphTransforms[glyphIndex] = newTX; } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java index c3c94d8..95a806a 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java @@ -38,6 +38,8 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; +import gnu.classpath.Pointer; + import gnu.java.awt.ClasspathToolkit; import gnu.java.awt.peer.ClasspathFontPeer; import gnu.java.awt.font.opentype.NameDecoder; @@ -172,6 +174,14 @@ public class GdkFontPeer extends ClasspathFontPeer private ByteBuffer nameTable = null; + /** + * The pointer to the native font data. + * + * This field is manipulated by native code. Don't change or remove + * without adjusting the native code. + */ + private Pointer nativeFont; + private native void initState (); private native void dispose (); private native void setFont (String family, int style, int size); @@ -351,7 +361,7 @@ public class GdkFontPeer extends ClasspathFontPeer return NameDecoder.getName(nameTable, name, locale); } - public boolean canDisplay (Font font, char c) + public boolean canDisplay (Font font, int c) { // FIXME: inquire with pango return true; diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java index bd6daa2..67040b8 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java @@ -52,6 +52,8 @@ import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.util.Locale; +import gnu.classpath.Pointer; + public class GdkGraphicsEnvironment extends ClasspathGraphicsEnvironment { private final int native_state = GtkGenericPeer.getUniqueInteger (); @@ -59,15 +61,24 @@ public class GdkGraphicsEnvironment extends ClasspathGraphicsEnvironment private GdkScreenGraphicsDevice defaultDevice; private GdkScreenGraphicsDevice[] devices; - + + /** + * The pointer to the native display resource. + * + * This field is manipulated by native code. Don't change or remove + * without adjusting the native code. + */ + private Pointer display; + static { System.loadLibrary("gtkpeer"); - initStaticState (); + GtkToolkit.initializeGlobalIDs(); + initIDs(); } - static native void initStaticState(); + private static native void initIDs(); public GdkGraphicsEnvironment () { diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java index 6f6ea56..e52bf05 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -68,6 +68,8 @@ import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; +import gnu.classpath.Pointer; + public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder { static @@ -94,6 +96,14 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder // the current set of ImageConsumers for this decoder Vector curr; + /** + * The pointer to the native pixbuf loader. + * + * This field is manipulated by native code. Don't change or remove + * without adjusting the native code. + */ + private Pointer nativeDecoder; + // interface to GdkPixbuf // These native functions should be called with the pixbufLock held. native void initState (); diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java index 6d0218d..d3e9774 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java @@ -91,4 +91,9 @@ public class GdkRobotPeer implements RobotPeer return pixels; } + + public void dispose() + { + // Nothing to do here yet. + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java index a69c6f0..7ef4645 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java @@ -46,6 +46,8 @@ import java.awt.Rectangle; import java.awt.Window; import java.util.ArrayList; +import gnu.classpath.Pointer; + class GdkScreenGraphicsDevice extends GraphicsDevice { private final int native_state = GtkGenericPeer.getUniqueInteger (); @@ -85,15 +87,23 @@ class GdkScreenGraphicsDevice extends GraphicsDevice * method must be called. */ DisplayMode fixedDisplayMode; - + + /** + * The pointer to the native screen resource. + * + * This field is manipulated by native code. Don't change or remove + * without adjusting the native code. + */ + private Pointer screen; + static { System.loadLibrary("gtkpeer"); - - initStaticState (); + GtkToolkit.initializeGlobalIDs(); + initIDs(); } - static native void initStaticState(); + static native void initIDs(); GdkScreenGraphicsDevice (GdkGraphicsEnvironment e) { diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java index a7ae8e1..16c20ee 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -616,11 +616,18 @@ public class GtkComponentPeer extends GtkGenericPeer setVisible (true); } - protected void postMouseEvent(int id, long when, int mods, int x, int y, + protected void postMouseEvent(int id, long when, int mods, int x, int y, int clickCount, boolean popupTrigger) { - q().postEvent(new MouseEvent(awtComponent, id, when, mods, x, y, - clickCount, popupTrigger)); + // It is important to do the getLocationOnScreen() here, instead + // of using the old MouseEvent constructors, because + // Component.getLocationOnScreen() locks on the AWT lock, which can + // trigger a deadlock. You don't want this. + Point locOnScreen = getLocationOnScreen(); + q().postEvent(new MouseEvent(awtComponent, id, when, mods, x, y, + locOnScreen.x + x, locOnScreen.y + y, + clickCount, popupTrigger, + MouseEvent.NOBUTTON)); } /** @@ -899,4 +906,14 @@ public class GtkComponentPeer extends GtkGenericPeer // FIXME: implement } + + public boolean requestFocus(Component lightweightChild, boolean temporary, + boolean focusedWindowChangeAllowed, + long time, sun.awt.CausedFocusEvent.Cause cause) + { + // TODO: Implement this properly and remove the other requestFocus() + // methods. + return true; + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java index b35be52..4278a45 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java @@ -244,6 +244,13 @@ public class GtkFramePeer extends GtkWindowPeer // TODO Auto-generated method stub return false; } + + public Rectangle getBoundsPrivate() + { + // TODO: Implement this properly. + throw new InternalError("Not yet implemented"); + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java index 468c46d..8d63699 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java @@ -43,6 +43,8 @@ import java.awt.Font; import java.awt.Toolkit; import java.awt.event.ActionEvent; +import gnu.classpath.Pointer; + public class GtkGenericPeer { // Used by Native State Association (NSA) functions to map @@ -56,6 +58,40 @@ public class GtkGenericPeer protected final Object awtWidget; /** + * The pointer to the native GTK widget. + * + * This field is manipulated by native code. Don't change or remove + * without adjusting the native code. + */ + private Pointer widget; + + /** + * The pointer to the global reference to this object. The native + * code creates a JNI global reference of the peer object to be able + * to pass it to the event callbacks. It gets stored here, so that + * we can later delete it in the dispose() method. + * + * This field is manipulated by native code. Don't change or remove + * without adjusting the native code. + */ + private Pointer globalRef; + + /** + * We initialize the field IDs that are used by native code here because + * these remain valid until a class gets unloaded. + */ + static + { + GtkToolkit.initializeGlobalIDs(); + initIDs(); + } + + /** + * Initializes the field IDs that are used by the native code. + */ + private static native void initIDs(); + + /** * Dispose of our native state. Calls gtk_widget_destroy on the * native widget and removes the awtWidget from the native state * tables. Should be overridden by subclasses if this is not (all) diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java index df18d39..dc9c715 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -144,10 +144,39 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit static native void gtkQuit(); + /** + * Initializes field IDs that are used by native code. + */ + private static native void initIDs(); + + /** + * True when the field IDs are already initialized, false otherwise. + */ + private static boolean initializedGlobalIDs = false; + + /** + * Initializes some global fieldIDs for use in the native code. This is + * called by a couple of classes in the GTK peers to ensure that + * some necessary stuff is loaded. + */ + static synchronized void initializeGlobalIDs() + { + if (! initializedGlobalIDs) + { + initIDs(); + initializedGlobalIDs = true; + } + } + static { System.loadLibrary("gtkpeer"); - + + /** + * Gotta do that first. + */ + initializeGlobalIDs(); + int portableNativeSync; String portNatSyncProp = System.getProperty("gnu.classpath.awt.gtk.portable.native.sync"); @@ -716,4 +745,17 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public native int getMouseNumberOfButtons(); + @Override + public boolean isModalExclusionTypeSupported + (Dialog.ModalExclusionType modalExclusionType) + { + return false; + } + + @Override + public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) + { + return false; + } + } // class GtkToolkit diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java index 1451dd9..d805415 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java @@ -398,4 +398,29 @@ public class GtkWindowPeer extends GtkContainerPeer { return new Rectangle(x, y, width, height); } + + public void updateIconImages() + { + // TODO: Implement properly. + } + + public void updateMinimumSize() + { + // TODO: Implement properly. + } + + public void setModalBlocked(java.awt.Dialog d, boolean b) + { + // TODO: Implement properly. + } + + public void updateFocusableWindowState() + { + // TODO: Implement properly. + } + + public void setAlwaysOnTop(boolean b) + { + // TODO: Implement properly. + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java index 8843886..ad5cd5e 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java @@ -86,7 +86,17 @@ public class VolatileImageGraphics extends ComponentGraphics public GraphicsConfiguration getDeviceConfiguration() { - return owner.component.getGraphicsConfiguration(); + GraphicsConfiguration conf; + if (owner.component != null) + { + conf = owner.component.getGraphicsConfiguration(); + } + else + { + return java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + } + return conf; } public Graphics create() diff --git a/libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java b/libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java index 96798c9..58b5f33 100644 --- a/libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java +++ b/libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java @@ -368,4 +368,18 @@ public class HeadlessToolkit return graphicsEnv; } + @Override + public boolean isModalExclusionTypeSupported + (Dialog.ModalExclusionType modalExclusionType) + { + return false; + } + + @Override + public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) + { + return false; + } + + } diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java index 4d7b58c..334f590 100644 --- a/libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java @@ -821,4 +821,14 @@ public class QtComponentPeer extends NativeWrapper implements ComponentPeer { // TODO Auto-generated method stub } + + public boolean requestFocus(Component lightweightChild, boolean temporary, + boolean focusedWindowChangeAllowed, + long time, sun.awt.CausedFocusEvent.Cause cause) + { + // TODO: Implement this properly and remove the other requestFocus() + // methods. + return true; + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java b/libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java index 2438fcc..3b182b5 100644 --- a/libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java +++ b/libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java @@ -94,7 +94,7 @@ public class QtFontMetrics extends FontMetrics // ****************** Package private *************************** - native boolean canDisplay( char c ); + native boolean canDisplay( int c ); // ****************** Public methods **************************** diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java index 6ffe3f6..bd16daf 100644 --- a/libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java @@ -98,7 +98,7 @@ public class QtFontPeer extends ClasspathFontPeer // ****************** ClasspathFontPeer Methods. - public boolean canDisplay (Font font, char c) + public boolean canDisplay (Font font, int c) { return metrics.canDisplay( c ); } diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java index b2c6a59..e3b5789 100644 --- a/libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java +++ b/libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java @@ -155,4 +155,10 @@ public class QtFramePeer extends QtWindowPeer implements FramePeer return false; } + public Rectangle getBoundsPrivate() + { + // TODO: Implement this properly. + throw new InternalError("Not yet implemented"); + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java b/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java index 9b53b27..4cea976 100644 --- a/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java +++ b/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java @@ -452,4 +452,19 @@ public class QtToolkit extends ClasspathToolkit // return new QtEmbeddedWindowPeer( this, w ); return null; } + + @Override + public boolean isModalExclusionTypeSupported + (Dialog.ModalExclusionType modalExclusionType) + { + return false; + } + + @Override + public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) + { + return false; + } + + } diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java index 7baf8e6..e0a9e8c 100644 --- a/libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java @@ -77,4 +77,29 @@ public class QtWindowPeer extends QtContainerPeer implements WindowPeer return false; } + public void updateIconImages() + { + // TODO: Implement properly. + } + + public void updateMinimumSize() + { + // TODO: Implement properly. + } + + public void setModalBlocked(java.awt.Dialog d, boolean b) + { + // TODO: Implement properly. + } + + public void updateFocusableWindowState() + { + // TODO: Implement properly. + } + + public void setAlwaysOnTop(boolean b) + { + // TODO: Implement properly. + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java index 531d6f2..192d612 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java @@ -1,5 +1,5 @@ /* SwingButtonPeer.java -- A Swing based peer for AWT buttons - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,6 +44,7 @@ import java.awt.Image; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.peer.ButtonPeer; @@ -70,12 +71,12 @@ public class SwingButtonPeer extends JButton implements SwingComponent { - Button button; + Button button; - SwingButton(Button button) - { - this.button = button; - } + SwingButton(Button button) + { + this.button = button; + } /** * Overridden so that this method returns the correct value even without a @@ -184,6 +185,26 @@ public class SwingButtonPeer par = button.getParent(); return par; } + + /** + * Handles focus events by forwarding it to + * processFocusEvent(). + * + * @param ev the Focus event + */ + public void handleFocusEvent(FocusEvent ev) + { + processFocusEvent(ev); + } + + public void requestFocus() { + SwingButtonPeer.this.requestFocus(awtComponent, false, true, 0); + } + + public boolean requestFocus(boolean temporary) { + return SwingButtonPeer.this.requestFocus(awtComponent, temporary, + true, 0); + } } /** diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java new file mode 100755 index 0000000..a8e3cb0 --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java @@ -0,0 +1,261 @@ +/* SwingCheckboxPeer.java -- A Swing based peer for AWT checkboxes + Copyright (C) 2007 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.peer.swing; + +import java.awt.Button; +import java.awt.Checkbox; +import java.awt.CheckboxGroup; +import java.awt.Container; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Label; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.peer.CheckboxPeer; + +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JToggleButton; + +/** + * A CheckboxPeer implementation that is backed by the Swing JCheckBox. + */ +public class SwingCheckboxPeer extends SwingComponentPeer implements + CheckboxPeer { + + /** + * A spezialized Swing checkbox used to paint the checkbox for the + * AWT checkbox. + */ + private class SwingCheckbox + extends JCheckBox + implements SwingComponent + { + Checkbox checkbox; + + SwingCheckbox(Checkbox checkbox) + { + this.checkbox = checkbox; + } + + /** + * Returns this checkbox. + * + * @return this + */ + public JComponent getJComponent() + { + return this; + } + + /** + * Handles mouse events by forwarding it to + * processMouseEvent(). + * + * @param ev the mouse event + */ + public void handleMouseEvent(MouseEvent ev) + { + ev.setSource(this); + processMouseEvent(ev); + } + + /** + * Handles mouse motion events by forwarding it to + * processMouseMotionEvent(). + * + * @param ev the mouse motion event + */ + public void handleMouseMotionEvent(MouseEvent ev) + { + ev.setSource(this); + processMouseMotionEvent(ev); + } + + /** + * Handles key events by forwarding it to processKeyEvent(). + * + * @param ev the mouse event + */ + public void handleKeyEvent(KeyEvent ev) + { + ev.setSource(this); + processKeyEvent(ev); + } + + /** + * Handles focus events by forwarding it to + * processFocusEvent(). + * + * @param ev the Focus event + */ + public void handleFocusEvent(FocusEvent ev) + { + processFocusEvent(ev); + } + + /** + * Overridden so that this method returns the correct value even without a + * peer. + * + * @return the screen location of the button + */ + public Point getLocationOnScreen() + { + return SwingCheckboxPeer.this.getLocationOnScreen(); + } + + /** + * Overridden so that the isShowing method returns the correct value + * for the swing button, even if it has no peer on its own. + * + * @return true if the button is currently showing, + * false otherwise + */ + public boolean isShowing() + { + boolean retVal = false; + if (checkbox != null) + retVal = checkbox.isShowing(); + return retVal; + } + + /** + * Overridden, so that the Swing button can create an Image without its + * own peer. + * + * @param w the width of the image + * @param h the height of the image + * + * @return an image + */ + public Image createImage(int w, int h) + { + return SwingCheckboxPeer.this.createImage(w, h); + } + + public Graphics getGraphics() + { + return SwingCheckboxPeer.this.getGraphics(); + } + + public Container getParent() + { + Container par = null; + if (checkbox != null) + par = checkbox.getParent(); + return par; + } + + public void requestFocus() { + SwingCheckboxPeer.this.requestFocus(awtComponent, false, true, 0); + } + + public boolean requestFocus(boolean temporary) { + return SwingCheckboxPeer.this.requestFocus(awtComponent, temporary, + true, 0); + } + } + + /** + * Listens for ActionEvents on the Swing button and triggers corresponding + * ActionEvents on the AWT button. + */ + class SwingCheckboxListener implements ItemListener + { + Checkbox awtCheckbox; + + SwingCheckboxListener(Checkbox checkbox) + { + awtCheckbox = checkbox; + } + + /** + * Receives notification when an action was performend on the button. + * + * @param event the action event + */ + public void itemStateChanged(ItemEvent event) + { + awtCheckbox.setState(event.getStateChange()==ItemEvent.SELECTED); + ItemListener[] l = awtCheckbox.getItemListeners(); + if (l.length == 0) + return; + ItemEvent ev = new ItemEvent(awtCheckbox, ItemEvent.ITEM_STATE_CHANGED, + awtCheckbox, event.getStateChange()); + for (int i = 0; i < l.length; ++i) + l[i].itemStateChanged(ev); + } + } + + /** + * Creates a new SwingCheckboxPeer instance. + */ + public SwingCheckboxPeer(Checkbox checkbox) + { + SwingCheckbox swingCheckbox = new SwingCheckbox(checkbox); + swingCheckbox.addItemListener(new SwingCheckboxListener(checkbox)); + + init(checkbox, swingCheckbox); + setLabel(checkbox.getLabel()); + setState(checkbox.getState()); + } + + public void setCheckboxGroup(CheckboxGroup group) + { + // TODO: Implement this. + } + + public void setLabel(String label) + { + ((JToggleButton) swingComponent).setText(label); + } + + public void setState(boolean state) + { + ((JToggleButton) swingComponent).setSelected(state); + } + +} diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java index 04ca729..d22f55d 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java @@ -37,6 +37,7 @@ exception statement from your version. */ package gnu.java.awt.peer.swing; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; @@ -86,4 +87,13 @@ public interface SwingComponent * @param ev the key event */ void handleKeyEvent(KeyEvent ev); + + /** + * Handles a focus event. This is usually forwarded to + * {@link Component#processFocusEvent(FocusEvent)} of the swing + * component. + * + * @param ev the focus event + */ + void handleFocusEvent(FocusEvent ev); } diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java index bfa14dd..71a7bac 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java @@ -1,5 +1,5 @@ /* SwingComponentPeer.java -- An abstract base class for Swing based peers - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,6 +45,7 @@ import java.awt.Component; import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; @@ -54,6 +55,7 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.BufferCapabilities.FlipContents; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.PaintEvent; @@ -349,12 +351,7 @@ public class SwingComponentPeer */ public Dimension getMinimumSize() { - Dimension retVal; - if (swingComponent != null) - retVal = swingComponent.getJComponent().getMinimumSize(); - else - retVal = new Dimension(0, 0); - return retVal; + return minimumSize(); } /** @@ -367,12 +364,7 @@ public class SwingComponentPeer */ public Dimension getPreferredSize() { - Dimension retVal; - if (swingComponent != null) - retVal = swingComponent.getJComponent().getPreferredSize(); - else - retVal = new Dimension(0, 0); - return retVal; + return preferredSize(); } /** @@ -395,30 +387,28 @@ public class SwingComponentPeer public void handleEvent(AWTEvent e) { switch (e.getID()) - { + { case PaintEvent.UPDATE: case PaintEvent.PAINT: - // Need to synchronize to avoid threading problems on the - // paint event list. - // We must synchronize on the tree lock first to avoid deadlock, - // because Container.paint() will grab it anyway. - synchronized (this) + if (awtComponent.isShowing()) { - assert paintArea != null; - if (awtComponent.isShowing()) + Rectangle clip ; + synchronized (this) { - Graphics g = awtComponent.getGraphics(); - try - { - Rectangle clip = paintArea; - g.clipRect(clip.x, clip.y, clip.width, clip.height); - peerPaint(g, e.getID() == PaintEvent.UPDATE); - } - finally - { - g.dispose(); - paintArea = null; - } + coalescePaintEvent((PaintEvent) e); + assert paintArea != null; + clip = paintArea; + paintArea = null; + } + Graphics g = awtComponent.getGraphics(); + try + { + g.clipRect(clip.x, clip.y, clip.width, clip.height); + peerPaint(g, e.getID() == PaintEvent.UPDATE); + } + finally + { + g.dispose(); } } break; @@ -438,10 +428,14 @@ public class SwingComponentPeer case KeyEvent.KEY_TYPED: handleKeyEvent((KeyEvent) e); break; + case FocusEvent.FOCUS_GAINED: + case FocusEvent.FOCUS_LOST: + handleFocusEvent((FocusEvent)e); + break; default: // Other event types are not handled here. break; - } + } } /** @@ -574,13 +568,16 @@ public class SwingComponentPeer * This is implemented to call repaint() on the Swing component. * * @param tm number of milliseconds to wait with repainting - * @param x the X coordinate of the upper left corner of the damaged rectangle - * @param y the Y coordinate of the upper left corner of the damaged rectangle + * @param x the X coordinate of the upper left corner of the damaged + * rectangle + * @param y the Y coordinate of the upper left corner of the damaged + * rectangle * @param width the width of the damaged rectangle * @param height the height of the damaged rectangle */ public void repaint(long tm, int x, int y, int width, int height) { + // NOTE: This is never called by AWT but is mandated by the peer interface. if (swingComponent != null) swingComponent.getJComponent().repaint(tm, x, y, width, height); else @@ -602,8 +599,10 @@ public class SwingComponentPeer */ public void requestFocus() { - if (swingComponent != null) - swingComponent.getJComponent().requestFocus(); + // NOTE: This is never called by AWT but is mandated by the peer interface. + Toolkit tk = Toolkit.getDefaultToolkit(); + EventQueue q = tk.getSystemEventQueue(); + q.postEvent(new FocusEvent(awtComponent, FocusEvent.FOCUS_GAINED, false)); } /** @@ -612,18 +611,22 @@ public class SwingComponentPeer * * This calls requestFocus() on the Swing component. * - * @param source TODO - * @param bool1 TODO - * @param bool2 TODO - * @param x TODO + * @param source the actual component that requests focus (may be a + * lightweight descendant of the heavyweight container) + * @param tmp true when the change is temporary + * @param allowWindowFocus + * @param tm the timestamp of the focus change * - * @return TODO + * @return true when the focus change is guaranteed to be granted, false + * otherwise */ - public boolean requestFocus(Component source, boolean bool1, boolean bool2, long x) + public boolean requestFocus(Component source, boolean tmp, + boolean allowWindowFocus, long tm) { - if (swingComponent != null) - swingComponent.getJComponent().requestFocus(); - return swingComponent != null; + Toolkit tk = Toolkit.getDefaultToolkit(); + EventQueue q = tk.getSystemEventQueue(); + q.postEvent(new FocusEvent(source, FocusEvent.FOCUS_GAINED, tmp)); + return true; } /** @@ -1101,6 +1104,19 @@ public class SwingComponentPeer } /** + * Handles focus events on the component. This is usually forwarded to the + * SwingComponent's processFocusEvent() method. + * + * @param e the key event + */ + protected void handleFocusEvent(FocusEvent e) + { + if (swingComponent != null) + swingComponent.handleFocusEvent(e); + } + + + /** * Returns the AWT component for this peer. * * @return the AWT component for this peer @@ -1109,4 +1125,12 @@ public class SwingComponentPeer { return awtComponent; } + + public boolean requestFocus(Component lightweightChild, boolean temporary, + boolean focusedWindowChangeAllowed, + long time, sun.awt.CausedFocusEvent.Cause cause) + { + return true; + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java index c78b644..2d5d97f 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java @@ -1,5 +1,5 @@ /* SwingContainerPeer.java -- A Swing based peer for AWT containers - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -92,7 +92,7 @@ public class SwingContainerPeer * @see #peerPaintChildren(Graphics) * @see #removeHeavyweightDescendent(Component) */ - synchronized void addHeavyweightDescendent(Component comp) + protected synchronized void addHeavyweightDescendent(Component comp) { heavyweightDescendents.add(comp); focusOwner = null; @@ -106,13 +106,25 @@ public class SwingContainerPeer * @see #peerPaintChildren(Graphics) * @see #addHeavyweightDescendent(Component) */ - synchronized void removeHeavyweightDescendent(Component comp) + protected synchronized void removeHeavyweightDescendent(Component comp) { heavyweightDescendents.remove(comp); focusOwner = null; } /** + * Returns an array of all registered heavyweight descendents. + * + * @return all registered heavyweight descendents + */ + protected Component[] getHeavyweightDescendents() + { + Component[] heavyweights = new Component[heavyweightDescendents.size()]; + heavyweights = (Component[]) heavyweightDescendents.toArray(heavyweights); + return heavyweights; + } + + /** * Returns the insets of the container. * * This is implemented to return the insets of the Swing container. @@ -339,7 +351,7 @@ public class SwingContainerPeer { Component owner = getFocusOwner(); if(owner != null) - owner.dispatchEvent(e); + owner.getPeer().handleEvent(e); else super.handleKeyEvent(e); } diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java index 349c5a0..55c394e 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java @@ -1,5 +1,5 @@ /* SwingLabelPeer.java -- A Swing based peer for AWT labels - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,7 @@ import java.awt.Graphics; import java.awt.Image; import java.awt.Label; import java.awt.Point; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.peer.LabelPeer; @@ -120,6 +121,17 @@ public class SwingLabelPeer } /** + * Handles focus events by forwarding it to + * processFocusEvent(). + * + * @param ev the Focus event + */ + public void handleFocusEvent(FocusEvent ev) + { + processFocusEvent(ev); + } + + /** * Overridden so that this method returns the correct value even without a * peer. * diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java index aca2070..22a6052 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java @@ -1,5 +1,5 @@ /* SwingListPeer.java -- A Swing based peer for AWT lists - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,6 +46,7 @@ import java.awt.Image; import java.awt.List; import java.awt.Point; import java.awt.Rectangle; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.peer.ListPeer; @@ -129,6 +130,17 @@ public class SwingListPeer } /** + * Handles focus events by forwarding it to processFocusEvent(). + * + * @param ev the Focus event + */ + public void handleFocusEvent(FocusEvent ev) + { + processFocusEvent(ev); + } + + + /** * Overridden so that this method returns the correct value even without a * peer. * diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java index 3cea62a..37c6dbc 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java @@ -1,5 +1,5 @@ /* SwingPanelPeer.java -- A PanelPeer based on Swing - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,7 +47,7 @@ import java.awt.peer.PanelPeer; * @author Roman Kennke (kennke@aicas.com) */ // TODO: Maybe base implementation on JPanel. However, this doesn't seem -// necessary, but might be good for more consistend Look. +// necessary, but might be good for more consistent Look. public class SwingPanelPeer extends SwingContainerPeer implements PanelPeer diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java index 04ac011..2c438a1 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java @@ -1,5 +1,5 @@ /* SwingTextAreaPeer.java -- A Swing based peer for AWT textareas - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,14 +45,20 @@ import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.TextArea; +import java.awt.event.ComponentEvent; +import java.awt.event.FocusEvent; +import java.awt.event.HierarchyEvent; +import java.awt.event.InputMethodEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; import java.awt.im.InputMethodRequests; import java.awt.peer.TextAreaPeer; import javax.swing.JComponent; import javax.swing.JScrollPane; import javax.swing.JTextArea; +import javax.swing.JViewport; import javax.swing.text.BadLocationException; public class SwingTextAreaPeer @@ -65,15 +71,19 @@ public class SwingTextAreaPeer * * @author Roman Kennke (kennke@aicas.com) */ - private class SwingTextArea + private class SwingScrollPane extends JScrollPane implements SwingComponent { - SwingTextArea(Component comp) + SwingTextArea textArea; + + SwingScrollPane(SwingTextArea textArea) { - super(comp, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + super(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + + this.textArea = textArea; } /** @@ -94,8 +104,17 @@ public class SwingTextAreaPeer */ public void handleMouseEvent(MouseEvent ev) { - ev.setSource(this); - dispatchEvent(ev); + JViewport viewPort = getViewport(); + if(viewPort.contains(ev.getPoint())) + { + ev.setSource(textArea); + textArea.dispatchEvent(ev); + } + else + { + ev.setSource(this); + this.dispatchEvent(ev); + } } /** @@ -114,7 +133,7 @@ public class SwingTextAreaPeer */ public void handleMouseMotionEvent(MouseEvent ev) { - processMouseMotionEvent(ev); + textArea.processMouseMotionEvent(ev); } /** @@ -124,7 +143,18 @@ public class SwingTextAreaPeer */ public void handleKeyEvent(KeyEvent ev) { - processKeyEvent(ev); + textArea.processKeyEvent(ev); + } + + /** + * Handles focus events by forwarding it to + * processFocusEvent(). + * + * @param ev the Focus event + */ + public void handleFocusEvent(FocusEvent ev) + { + textArea.processFocusEvent(ev); } /** @@ -179,35 +209,160 @@ public class SwingTextAreaPeer par = SwingTextAreaPeer.this.awtComponent.getParent(); return par; } + + public void requestFocus() { + SwingTextAreaPeer.this.requestFocus(awtComponent, false, true, 0); + } + + public boolean requestFocus(boolean temporary) { + return SwingTextAreaPeer.this.requestFocus(awtComponent, temporary, + true, 0); + } + } + private class SwingTextArea extends JTextArea + { + /** + * Make this method accessible in this Package. + */ + protected final void processComponentKeyEvent(KeyEvent e) + { + super.processComponentKeyEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processMouseMotionEvent(MouseEvent ev) + { + super.processMouseMotionEvent(ev); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processComponentEvent(ComponentEvent e) + { + super.processComponentEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processFocusEvent(FocusEvent e) + { + super.processFocusEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processHierarchyBoundsEvent(HierarchyEvent e) + { + super.processHierarchyBoundsEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processHierarchyEvent(HierarchyEvent e) + { + super.processHierarchyEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processInputMethodEvent(InputMethodEvent e) + { + super.processInputMethodEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processMouseEvent(MouseEvent e) + { + super.processMouseEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processMouseWheelEvent(MouseWheelEvent e) + { + super.processMouseWheelEvent(e); + } + + /** + * Make this method accessible in this Package. + */ + protected final void processKeyEvent(KeyEvent e) + { + super.processKeyEvent(e); + } + + public void requestFocus() { + SwingTextAreaPeer.this.requestFocus(awtComponent, false, true, 0); + } + + public boolean requestFocus(boolean temporary) { + return SwingTextAreaPeer.this.requestFocus(awtComponent, temporary, + true, 0); + } + } + /** * The actual JTextArea. */ - private JTextArea jTextArea; + private SwingTextArea jTextArea; public SwingTextAreaPeer(TextArea textArea) { super(); - System.err.println("new SwingTextAreaPeer"); - jTextArea = new JTextArea(); - SwingTextArea swingArea = new SwingTextArea(jTextArea); + jTextArea = new SwingTextArea(); + SwingScrollPane swingArea = new SwingScrollPane(jTextArea); init(textArea, swingArea); + JViewport viewport = new JViewport() + { + public Image createImage(int width, int height) + { + return awtComponent.createImage(width, height); + } + }; + + viewport.setView(jTextArea); + swingArea.setViewport(viewport); // Pull over the text from the text area. setText(textArea.getText()); + + // Pull over the number of rows and columns + // if non were set use default values + int columns = textArea.getColumns(); + int rows = textArea.getRows(); + + if(columns == 0 && rows == 0) + { + columns = 25; + textArea.setColumns(columns); + rows = 5; + textArea.setRows(rows); + } + + jTextArea.setColumns(columns); + jTextArea.setRows(rows); } public Dimension getMinimumSize(int rows, int cols) { - // TODO Auto-generated method stub - return null; + return jTextArea.getMinimumSize(); } public Dimension getPreferredSize(int rows, int cols) { - // TODO Auto-generated method stub - return null; + return jTextArea.getPreferredSize(); } public void insert(String text, int pos) @@ -220,16 +375,24 @@ public class SwingTextAreaPeer jTextArea.insert(text, pos); } + public Dimension minimumSize() + { + return jTextArea.getMinimumSize(); + } + + public Dimension preferredSize() + { + return jTextArea.getPreferredSize(); + } + public Dimension minimumSize(int rows, int cols) { - // TODO Auto-generated method stub - return null; + return jTextArea.getMinimumSize(); } public Dimension preferredSize(int rows, int cols) { - // TODO Auto-generated method stub - return null; + return jTextArea.getPreferredSize(); } public void replaceRange(String text, int start, int end) @@ -310,8 +473,16 @@ public class SwingTextAreaPeer public void setText(String text) { - System.err.println("setText: " + text); jTextArea.setText(text); } + public void reshape(int x, int y, int width, int height) + { + if (swingComponent != null) + { + swingComponent.getJComponent().setBounds(x, y, width, height); + swingComponent.getJComponent().validate(); + } + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java index d7d574a..29a689d 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java @@ -1,5 +1,5 @@ /* SwingTextFieldPeer.java -- A Swing based peer for AWT textfields - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,6 +44,7 @@ import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.TextField; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.im.InputMethodRequests; @@ -72,13 +73,13 @@ public class SwingTextFieldPeer implements SwingComponent { - TextField textField; - - SwingTextField(TextField textField) - { - this.textField = textField; - } - + TextField textField; + + SwingTextField(TextField textField) + { + this.textField = textField; + } + /** * Overridden to provide normal behaviour even without a real peer * attached. @@ -91,8 +92,8 @@ public class SwingTextFieldPeer } /** - * Overridden so that the isShowing method returns the correct value for the - * swing button, even if it has no peer on its own. + * Overridden so that the isShowing method returns the correct value + * for the swing button, even if it has no peer on its own. * * @return true if the button is currently showing, * false otherwise @@ -162,6 +163,18 @@ public class SwingTextFieldPeer processKeyEvent(ev); } + /** + * Handles focus events by forwarding it to + * processFocusEvent(). + * + * @param ev the Focus event + */ + public void handleFocusEvent(FocusEvent ev) + { + processFocusEvent(ev); + } + + public Container getParent() { Container par = null; @@ -174,6 +187,16 @@ public class SwingTextFieldPeer { return SwingTextFieldPeer.this.getGraphics(); } + + public void requestFocus() { + SwingTextFieldPeer.this.requestFocus(awtComponent, false, true, 0); + } + + public boolean requestFocus(boolean temporary) { + return SwingTextFieldPeer.this.requestFocus(awtComponent, temporary, + true, 0); + } + } /** diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java index 166e1f4..6341405 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java @@ -40,6 +40,7 @@ package gnu.java.awt.peer.swing; import java.awt.Button; import java.awt.Canvas; +import java.awt.Dialog; import java.awt.Label; import java.awt.Menu; import java.awt.MenuBar; @@ -162,4 +163,19 @@ public abstract class SwingToolkit extends ClasspathToolkit { return new SwingTextFieldPeer(textField); } + + @Override + public boolean isModalExclusionTypeSupported + (Dialog.ModalExclusionType modalExclusionType) + { + return false; + } + + @Override + public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) + { + return false; + } + + } diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java index 531552d..bdc494e 100644 --- a/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java @@ -71,4 +71,29 @@ public abstract class SwingWindowPeer super(window); init(window, null); } + + public void updateIconImages() + { + // TODO: Implement properly. + } + + public void updateMinimumSize() + { + // TODO: Implement properly. + } + + public void setModalBlocked(java.awt.Dialog d, boolean b) + { + // TODO: Implement properly. + } + + public void updateFocusableWindowState() + { + // TODO: Implement properly. + } + + public void setAlwaysOnTop(boolean b) + { + // TODO: Implement properly. + } } diff --git a/libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java b/libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java index 8e0a31f..8cda31d 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java +++ b/libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java @@ -405,8 +405,12 @@ final class KeyboardMapping if ((xMods & Input.SHIFT_MASK) != 0) mods |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK; + if ((xMods & Input.META_MASK) != 0) + mods |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK; if ((xMods & Input.ALT_MASK) != 0) mods |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK; + if ((xMods & Input.MOD5_MASK) != 0) + mods |= KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK; if ((xMods & Input.CONTROL_MASK) != 0) mods |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK; diff --git a/libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java b/libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java new file mode 100644 index 0000000..131647f --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java @@ -0,0 +1,185 @@ +/* PixmapVolatileImage.java -- VolatileImage implementation around a Pixmap + Copyright (C) 2007 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.awt.peer.x; + +import gnu.x11.GC; +import gnu.x11.Pixmap; +import gnu.x11.image.Image; +import gnu.x11.image.ZPixmap; + +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.ImageCapabilities; +import java.awt.Point; +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.ComponentSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.ImageObserver; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.VolatileImage; +import java.awt.image.WritableRaster; + +/** + * A {@link VolatileImage} implementation that wraps an X Pixmap. + */ +class PixmapVolatileImage + extends VolatileImage +{ + + /** + * The shared capabilities instance. + */ + private static final ImageCapabilities caps = new ImageCapabilities(true); + + /** + * The underlying pixmap. + */ + private Pixmap pixmap; + + /** + * Creates a new PixmapVolatileImage. + * + * @param w the width of the image + * @param h the height of the image + */ + public PixmapVolatileImage(int w, int h) + { + GraphicsEnvironment env = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice(); + pixmap = new Pixmap(dev.getDisplay(), w, h); + + // Clear pixmap. + GC gc = new GC(pixmap); + gc.set_foreground(0xffffffff); + pixmap.fill_rectangle(gc, 0, 0, w, h); + + } + + @Override + public boolean contentsLost() + { + return false; + } + + @Override + public Graphics2D createGraphics() + { + return new XGraphics2D(pixmap); + } + + @Override + public ImageCapabilities getCapabilities() + { + return caps; + } + + @Override + public int getHeight() + { + return pixmap.height; + } + + @Override + public BufferedImage getSnapshot() + { + // TODO: Support non-24-bit resolutions. + int w = pixmap.width; + int h = pixmap.height; + ZPixmap zpixmap = (ZPixmap) pixmap.image(0, 0, w, h, 0xffffffff, + Image.Format.ZPIXMAP); + DataBuffer buffer = new ZPixmapDataBuffer(zpixmap); + SampleModel sm = new ComponentSampleModel(DataBuffer.TYPE_BYTE, w, h, 4, + w * 4, + new int[]{0, 1, 2, 3 }); + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); + ColorModel cm = new ComponentColorModel(cs, true, false, + Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createWritableRaster(sm, buffer, + new Point(0, 0)); + return new BufferedImage(cm, raster, false, null); + } + + @Override + public int getWidth() + { + return pixmap.width; + } + + @Override + public int validate(GraphicsConfiguration gc) + { + // TODO: Check compatibility with gc. + return IMAGE_OK; + } + + @Override + public int getHeight(ImageObserver observer) + { + return getHeight(); + } + + @Override + public Object getProperty(String name, ImageObserver observer) + { + return null; + } + + @Override + public int getWidth(ImageObserver observer) + { + return getWidth(); + } + + /** + * Returns the underlying X pixmap. This is used for the graphics code. + * + * @return the underlying X pixmap + */ + Pixmap getPixmap() + { + return pixmap; + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/x/XEventPump.java b/libjava/classpath/gnu/java/awt/peer/x/XEventPump.java index 870edf3..d376619 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XEventPump.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XEventPump.java @@ -97,8 +97,9 @@ public class XEventPump display = d; windows = new HashMap(); drag = -1; - Thread t = new Thread(this); - t.start(); + Thread thread = new Thread(this, "X Event Pump"); + thread.setDaemon(true); + thread.start(); } /** @@ -148,8 +149,9 @@ public class XEventPump private void handleEvent(Event xEvent) { - Integer key = new Integer(xEvent.window_id());; - Window awtWindow = (Window) windows.get(key); + + Integer key = null; + Window awtWindow = null; if (XToolkit.DEBUG) System.err.println("fetched event: " + xEvent); @@ -157,26 +159,45 @@ public class XEventPump { case ButtonPress.CODE: ButtonPress bp = (ButtonPress) xEvent; + key= new Integer(bp.event_window_id); + awtWindow = (Window) windows.get(key); // Create and post the mouse event. int button = bp.detail(); + + // AWT cannot handle more than 3 buttons and expects 0 instead. + if (button >= gnu.x11.Input.BUTTON3) + button = 0; drag = button; + MouseEvent mp = new MouseEvent(awtWindow, MouseEvent.MOUSE_PRESSED, - System.currentTimeMillis(), 0, + System.currentTimeMillis(), + KeyboardMapping.mapModifiers(bp.state()) | buttonToModifier(button), bp.event_x(), bp.event_y(), 1, false, button); Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mp); break; case ButtonRelease.CODE: ButtonRelease br = (ButtonRelease) xEvent; + key= new Integer(br.event_window_id); + awtWindow = (Window) windows.get(key); + + button = br.detail(); + // AWT cannot handle more than 3 buttons and expects 0 instead. + if (button >= gnu.x11.Input.BUTTON3) + button = 0; drag = -1; MouseEvent mr = new MouseEvent(awtWindow, MouseEvent.MOUSE_RELEASED, - System.currentTimeMillis(), 0, + System.currentTimeMillis(), + KeyboardMapping.mapModifiers(br.state()) | buttonToModifier(button), br.event_x(), br.event_y(), - 1, false, br.detail()); + 1, false, button); Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mr); break; case MotionNotify.CODE: MotionNotify mn = (MotionNotify) xEvent; + key= new Integer(mn.event_window_id); + awtWindow = (Window) windows.get(key); + MouseEvent mm; if (drag == -1) { @@ -195,6 +216,8 @@ public class XEventPump Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mm); break; case ConfigureNotify.CODE: + key= new Integer(((ConfigureNotify) xEvent).event_window_id); + awtWindow = (Window) windows.get(key); ConfigureNotify c = (ConfigureNotify) xEvent; if (XToolkit.DEBUG) System.err.println("resize request for window id: " + key); @@ -213,6 +236,8 @@ public class XEventPump } break; case Expose.CODE: + key= new Integer(((Expose) xEvent).window_id); + awtWindow = (Window) windows.get(key); Expose exp = (Expose) xEvent; if (XToolkit.DEBUG) System.err.println("expose request for window id: " + key); @@ -228,6 +253,8 @@ public class XEventPump break; case KeyPress.CODE: case KeyRelease.CODE: + key = new Integer(((Input) xEvent).event_window_id); + awtWindow = (Window) windows.get(key); handleKeyEvent(xEvent, awtWindow); break; default: @@ -282,6 +309,23 @@ public class XEventPump } + /** Translates an X button identifier to the AWT's MouseEvent modifier + * mask. As the AWT cannot handle more than 3 buttons those return + * 0. + */ + static int buttonToModifier(int button) + { + switch (button) + { + case gnu.x11.Input.BUTTON1: + return MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON1_MASK; + case gnu.x11.Input.BUTTON2: + return MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON2_MASK; + case gnu.x11.Input.BUTTON3: + return MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON3_MASK; + } -} + return 0; + } +} diff --git a/libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java b/libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java deleted file mode 100644 index 8183fed..0000000 --- a/libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java +++ /dev/null @@ -1,759 +0,0 @@ -/* XFontPeer.java -- The font peer for X - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.java.awt.peer.x; - -import java.awt.AWTError; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphVector; -import java.awt.font.LineMetrics; -import java.awt.font.TextAttribute; -import java.awt.geom.Rectangle2D; -import java.io.IOException; -import java.io.InputStream; -import java.text.CharacterIterator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; - -import gnu.java.awt.peer.ClasspathFontPeer; -import gnu.x11.Display; -import gnu.x11.Fontable; - -/** - * The bridge from AWT to X fonts. - * - * @author Roman Kennke (kennke@aicas.com) - */ -public class XFontPeer - extends ClasspathFontPeer -{ - - /** - * The font mapping as specified in the file fonts.properties. - */ - private static Properties fontProperties; - static - { - fontProperties = new Properties(); - InputStream in = XFontPeer.class.getResourceAsStream("fonts.properties"); - try - { - fontProperties.load(in); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - /** - * The FontMetrics implementation for XFontPeer. - */ - private class XFontMetrics - extends FontMetrics - { - /** - * The ascent of the font. - */ - int ascent; - - /** - * The descent of the font. - */ - int descent; - - /** - * The maximum of the character advances. - */ - private int maxAdvance; - - /** - * The internal leading. - */ - int leading; - - /** - * Cached string metrics. This caches string metrics locally so that the - * server doesn't have to be asked each time. - */ - private HashMap metricsCache; - - /** - * The widths of the characters indexed by the characters themselves. - */ - private int[] charWidths; - - /** - * Creates a new XFontMetrics for the specified font. - * - * @param font the font - */ - protected XFontMetrics(Font font) - { - super(font); - metricsCache = new HashMap(); - Fontable.FontReply info = getXFont().info(); - ascent = info.font_ascent(); - descent = info.font_descent(); - maxAdvance = info.max_bounds().character_width(); - leading = 0; // TODO: Not provided by X. Possible not needed. - - if (info.min_byte1() == 0 && info.max_byte1() == 0) - readCharWidthsLinear(info); - else - readCharWidthsNonLinear(info); - } - - /** - * Reads the character widths when specified in a linear fashion. That is - * when the min-byte1 and max-byte2 fields are both zero in the X protocol. - * - * @param info the font info reply - */ - private void readCharWidthsLinear(Fontable.FontReply info) - { - int startIndex = info.min_char_or_byte2(); - int endIndex = info.max_char_or_byte2(); - charWidths = new int[endIndex + 1]; - // All the characters before startIndex are zero width. - for (int i = 0; i < startIndex; i++) - { - charWidths[i] = 0; - } - // All the other character info is fetched from the font info. - int index = startIndex; - Iterator charInfos = info.char_infos().iterator(); - while (charInfos.hasNext()) - { - Fontable.FontReply.CharInfo charInfo = - (Fontable.FontReply.CharInfo) charInfos.next(); - charWidths[index] = charInfo.character_width(); - index++; - } - } - - private void readCharWidthsNonLinear(Fontable.FontReply info) - { - // TODO: Implement. - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Returns the ascent of the font. - * - * @return the ascent of the font - */ - public int getAscent() - { - return ascent; - } - - /** - * Returns the descent of the font. - * - * @return the descent of the font - */ - public int getDescent() - { - return descent; - } - - /** - * Returns the overall height of the font. This is the distance from - * baseline to baseline (usually ascent + descent + leading). - * - * @return the overall height of the font - */ - public int getHeight() - { - return ascent + descent; - } - - /** - * Returns the leading of the font. - * - * @return the leading of the font - */ - public int getLeading() - { - return leading; - } - - /** - * Returns the maximum advance for this font. - * - * @return the maximum advance for this font - */ - public int getMaxAdvance() - { - return maxAdvance; - } - - /** - * Determines the width of the specified character c. - * - * @param c the character - * - * @return the width of the character - */ - public int charWidth(char c) - { - int width; - if (c > charWidths.length) - width = charWidths['?']; - else - width = charWidths[c]; - return width; - } - - /** - * Determines the overall width of the specified string. - * - * @param c the char buffer holding the string - * @param offset the starting offset of the string in the buffer - * @param length the number of characters in the string buffer - * - * @return the overall width of the specified string - */ - public int charsWidth(char[] c, int offset, int length) - { - int width = 0; - if (c.length > 0 && length > 0) - { - String s = new String(c, offset, length); - width = stringWidth(s); - } - return width; - } - - /** - * Determines the overall width of the specified string. - * - * @param s the string - * - * @return the overall width of the specified string - */ - public int stringWidth(String s) - { - int width = 0; - if (s.length() > 0) - { - if (metricsCache.containsKey(s)) - { - width = ((Integer) metricsCache.get(s)).intValue(); - } - else - { - Fontable.TextExtentReply extents = getXFont().text_extent(s); - /* - System.err.println("string: '" + s + "' : "); - System.err.println("ascent: " + extents.getAscent()); - System.err.println("descent: " + extents.getDescent()); - System.err.println("overall ascent: " + extents.getOverallAscent()); - System.err.println("overall descent: " + extents.getOverallDescent()); - System.err.println("overall width: " + extents.getOverallWidth()); - System.err.println("overall left: " + extents.getOverallLeft()); - System.err.println("overall right: " + extents.getOverallRight()); - */ - width = extents.overall_width(); // + extents.overall_left(); - //System.err.println("String: " + s + ", width: " + width); - metricsCache.put(s, new Integer(width)); - } - } - //System.err.print("stringWidth: '" + s + "': "); - //System.err.println(width); - return width; - } - } - - /** - * The LineMetrics implementation for the XFontPeer. - */ - private class XLineMetrics - extends LineMetrics - { - - /** - * Returns the ascent of the font. - * - * @return the ascent of the font - */ - public float getAscent() - { - return fontMetrics.ascent; - } - - public int getBaselineIndex() - { - // FIXME: Implement this. - throw new UnsupportedOperationException(); - } - - public float[] getBaselineOffsets() - { - // FIXME: Implement this. - throw new UnsupportedOperationException(); - } - - /** - * Returns the descent of the font. - * - * @return the descent of the font - */ - public float getDescent() - { - return fontMetrics.descent; - } - - /** - * Returns the overall height of the font. This is the distance from - * baseline to baseline (usually ascent + descent + leading). - * - * @return the overall height of the font - */ - public float getHeight() - { - return fontMetrics.ascent + fontMetrics.descent; - } - - /** - * Returns the leading of the font. - * - * @return the leading of the font - */ - public float getLeading() - { - return fontMetrics.leading; - } - - public int getNumChars() - { - // FIXME: Implement this. - throw new UnsupportedOperationException(); - } - - public float getStrikethroughOffset() - { - return 0.F; // TODO: Provided by X?? - } - - public float getStrikethroughThickness() - { - return 1.F; // TODO: Provided by X?? - } - - public float getUnderlineOffset() - { - return 0.F; // TODO: Provided by X?? - } - - public float getUnderlineThickness() - { - return 1.F; // TODO: Provided by X?? - } - - } - - /** - * The X font. - */ - private gnu.x11.Font xfont; - - private String name; - - private int style; - - private int size; - - /** - * The font metrics for this font. - */ - XFontMetrics fontMetrics; - - /** - * Creates a new XFontPeer for the specified font name, style and size. - * - * @param name the font name - * @param style the font style (bold / italic / normal) - * @param size the size of the font - */ - public XFontPeer(String name, int style, int size) - { - super(name, style, size); - this.name = name; - this.style = style; - this.size = size; - } - - /** - * Creates a new XFontPeer for the specified font name and style - * attributes. - * - * @param name the font name - * @param atts the font attributes - */ - public XFontPeer(String name, Map atts) - { - super(name, atts); - String family = name; - if (family == null || family.equals("")) - family = (String) atts.get(TextAttribute.FAMILY); - if (family == null) - family = "SansSerif"; - - int size = 12; - Float sizeFl = (Float) atts.get(TextAttribute.SIZE); - if (sizeFl != null) - size = sizeFl.intValue(); - - int style = 0; - // Detect italic attribute. - Float posture = (Float) atts.get(TextAttribute.POSTURE); - if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR)) - style |= Font.ITALIC; - - // Detect bold attribute. - Float weight = (Float) atts.get(TextAttribute.WEIGHT); - if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0) - style |= Font.BOLD; - - this.name = name; - this.style = style; - this.size = size; - } - - /** - * Initializes the font peer with the specified attributes. This method is - * called from both constructors. - * - * @param name the font name - * @param style the font style - * @param size the font size - */ - private void init(String name, int style, int size) - { - GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice dev = env.getDefaultScreenDevice(); - if (dev instanceof XGraphicsDevice) - { - Display display = ((XGraphicsDevice) dev).getDisplay(); - String fontDescr = encodeFont(name, style, size); - if (XToolkit.DEBUG) - System.err.println("XLFD font description: " + fontDescr); - xfont = new gnu.x11.Font(display, fontDescr); - } - else - { - throw new AWTError("Local GraphicsEnvironment is not XWindowGraphicsEnvironment"); - } - } - - public boolean canDisplay(Font font, char c) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public String getSubFamilyName(Font font, Locale locale) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public String getPostScriptName(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public int getNumGlyphs(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public int getMissingGlyphCode(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public byte getBaselineFor(Font font, char c) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public String getGlyphName(Font font, int glyphIndex) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public GlyphVector createGlyphVector(Font font, FontRenderContext frc, - CharacterIterator ci) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public GlyphVector createGlyphVector(Font font, FontRenderContext ctx, - int[] glyphCodes) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc, - char[] chars, int start, int limit, - int flags) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - /** - * Returns the font metrics for the specified font. - * - * @param font the font for which to fetch the font metrics - * - * @return the font metrics for the specified font - */ - public FontMetrics getFontMetrics(Font font) - { - if (font.getPeer() != this) - throw new AWTError("The specified font has a different peer than this"); - - if (fontMetrics == null) - fontMetrics = new XFontMetrics(font); - return fontMetrics; - } - - /** - * Frees the font in the X server. - */ - protected void finalize() - { - if (xfont != null) - xfont.close(); - } - - public boolean hasUniformLineMetrics(Font font) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - /** - * Returns the line metrics for this font and the specified string and - * font render context. - */ - public LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin, - int limit, FontRenderContext rc) - { - return new XLineMetrics(); - } - - public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc) - { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); - } - - /** - * Encodes a font name + style + size specification into a X logical font - * description (XLFD) as described here: - * - * http://www.meretrx.com/e93/docs/xlfd.html - * - * This is implemented to look up the font description in the - * fonts.properties of this package. - * - * @param name the font name - * @param atts the text attributes - * - * @return the encoded font description - */ - static String encodeFont(String name, Map atts) - { - String family = name; - if (family == null || family.equals("")) - family = (String) atts.get(TextAttribute.FAMILY); - if (family == null) - family = "SansSerif"; - - int size = 12; - Float sizeFl = (Float) atts.get(TextAttribute.SIZE); - if (sizeFl != null) - size = sizeFl.intValue(); - - int style = 0; - // Detect italic attribute. - Float posture = (Float) atts.get(TextAttribute.POSTURE); - if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR)) - style |= Font.ITALIC; - - // Detect bold attribute. - Float weight = (Float) atts.get(TextAttribute.WEIGHT); - if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0) - style |= Font.BOLD; - - return encodeFont(name, style, size); - } - - /** - * Encodes a font name + style + size specification into a X logical font - * description (XLFD) as described here: - * - * http://www.meretrx.com/e93/docs/xlfd.html - * - * This is implemented to look up the font description in the - * fonts.properties of this package. - * - * @param name the font name - * @param style the font style - * @param size the font size - * - * @return the encoded font description - */ - static String encodeFont(String name, int style, int size) - { - StringBuilder key = new StringBuilder(); - key.append(validName(name)); - key.append('.'); - switch (style) - { - case Font.BOLD: - key.append("bold"); - break; - case Font.ITALIC: - key.append("italic"); - break; - case (Font.BOLD | Font.ITALIC): - key.append("bolditalic"); - break; - case Font.PLAIN: - default: - key.append("plain"); - - } - - String protoType = fontProperties.getProperty(key.toString()); - int s = validSize(size); - return protoType.replaceFirst("%d", String.valueOf(s * 10)); - } - - /** - * Checks the specified font name for a valid font name. If the font name - * is not known, then this returns 'sansserif' as fallback. - * - * @param name the font name to check - * - * @return a valid font name - */ - static String validName(String name) - { - String retVal; - if (name.equalsIgnoreCase("sansserif") - || name.equalsIgnoreCase("serif") - || name.equalsIgnoreCase("monospaced") - || name.equalsIgnoreCase("dialog") - || name.equalsIgnoreCase("dialoginput")) - { - retVal = name.toLowerCase(); - } - else - { - retVal = "sansserif"; - } - return retVal; - } - - /** - * Translates an arbitrary point size to a size that is typically available - * on an X server. These are the sizes 8, 10, 12, 14, 18 and 24. - * - * @param size the queried size - * @return the real available size - */ - private static final int validSize(int size) - { - int val; - if (size <= 9) - val = 8; - else if (size <= 11) - val = 10; - else if (size <= 13) - val = 12; - else if (size <= 17) - val = 14; - else if (size <= 23) - val = 18; - else - val = 24; - return val; - } - - /** - * Returns the X Font reference. This lazily loads the font when first - * requested. - * - * @return the X Font reference - */ - gnu.x11.Font getXFont() - { - if (xfont == null) - { - init(name, style, size); - } - return xfont; - } -} diff --git a/libjava/classpath/gnu/java/awt/peer/x/XFontPeer2.java b/libjava/classpath/gnu/java/awt/peer/x/XFontPeer2.java index ef9507f..ab3861b 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XFontPeer2.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XFontPeer2.java @@ -42,17 +42,21 @@ import java.awt.FontMetrics; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.font.LineMetrics; +import java.awt.font.TextAttribute; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.File; import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Locale; import java.util.Map; +import java.util.Properties; import gnu.java.awt.font.FontDelegate; import gnu.java.awt.font.FontFactory; @@ -62,11 +66,30 @@ public class XFontPeer2 extends ClasspathFontPeer { + /** + * The font mapping as specified in the file fonts.properties. + */ + private static Properties fontProperties; + static + { + fontProperties = new Properties(); + InputStream in = XFontPeer2.class.getResourceAsStream("fonts.properties"); + try + { + fontProperties.load(in); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + private class XLineMetrics extends LineMetrics { private Font font; + private GlyphVector glyphVector; // private CharacterIterator characterIterator; // private int begin; // private int limit; @@ -79,6 +102,8 @@ public class XFontPeer2 // begin = b; // limit = l; fontRenderContext = rc; + glyphVector = fontDelegate.createGlyphVector(font, fontRenderContext, + ci); } public float getAscent() @@ -86,7 +111,7 @@ public class XFontPeer2 return fontDelegate.getAscent(font.getSize(), fontRenderContext.getTransform(), fontRenderContext.isAntiAliased(), fontRenderContext.usesFractionalMetrics(), true); - } + } public int getBaselineIndex() { @@ -102,21 +127,18 @@ public class XFontPeer2 public float getDescent() { - return (int) fontDelegate.getDescent(font.getSize(), - new AffineTransform(), false, false, - false); + return (int) fontDelegate.getDescent(font.getSize(), IDENDITY, false, + false, false); } public float getHeight() { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); + return (float) glyphVector.getLogicalBounds().getHeight(); } public float getLeading() { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); + return getHeight() - getAscent() - getDescent(); } public int getNumChars() @@ -150,6 +172,11 @@ public class XFontPeer2 private class XFontMetrics extends FontMetrics { + /** + * A cached point instance, to be used in #charWidth(). + */ + private Point2D cachedPoint = new Point2D.Double(); + XFontMetrics(Font f) { super(f); @@ -157,22 +184,20 @@ public class XFontPeer2 public int getAscent() { - return (int) fontDelegate.getAscent(getFont().getSize(), - new AffineTransform(), false, false, - false); + return (int) fontDelegate.getAscent(getFont().getSize(), IDENDITY, + false, false, false); } public int getDescent() { - return (int) fontDelegate.getDescent(getFont().getSize(), - new AffineTransform(), false, false, - false); + return (int) fontDelegate.getDescent(getFont().getSize(), IDENDITY, + false, false, false); } public int getHeight() { GlyphVector gv = fontDelegate.createGlyphVector(getFont(), - new FontRenderContext(new AffineTransform(), false, false), + new FontRenderContext(IDENDITY, false, false), new StringCharacterIterator("m")); Rectangle2D b = gv.getVisualBounds(); return (int) b.getHeight(); @@ -180,8 +205,9 @@ public class XFontPeer2 public int charWidth(char c) { - Point2D advance = new Point2D.Double(); - fontDelegate.getAdvance(c, getFont().getSize(), new AffineTransform(), + int code = fontDelegate.getGlyphIndex(c); + Point2D advance = cachedPoint; + fontDelegate.getAdvance(code, font.getSize2D(), IDENDITY, false, false, true, advance); return (int) advance.getX(); } @@ -194,13 +220,18 @@ public class XFontPeer2 public int stringWidth(String s) { GlyphVector gv = fontDelegate.createGlyphVector(getFont(), - new FontRenderContext(new AffineTransform(), false, false), + new FontRenderContext(IDENDITY, false, false), new StringCharacterIterator(s)); Rectangle2D b = gv.getVisualBounds(); return (int) b.getWidth(); } } + /** + * The indendity transform, to be used in several methods. + */ + private static final AffineTransform IDENDITY = new AffineTransform(); + private FontDelegate fontDelegate; XFontPeer2(String name, int style, int size) @@ -208,7 +239,7 @@ public class XFontPeer2 super(name, style, size); try { - File fontfile = new File("/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf"); + File fontfile = new File("/usr/share/fonts/truetype/freefont/FreeSans.ttf"); FileInputStream in = new FileInputStream(fontfile); FileChannel ch = in.getChannel(); ByteBuffer buffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, @@ -239,7 +270,7 @@ public class XFontPeer2 } } - public boolean canDisplay(Font font, char c) + public boolean canDisplay(Font font, int c) { // FIXME: Implement this. throw new UnsupportedOperationException("Not yet implemented"); @@ -326,4 +357,112 @@ public class XFontPeer2 throw new UnsupportedOperationException("Not yet implemented"); } + /** + * Encodes a font name + style + size specification into a X logical font + * description (XLFD) as described here: + * + * http://www.meretrx.com/e93/docs/xlfd.html + * + * This is implemented to look up the font description in the + * fonts.properties of this package. + * + * @param name the font name + * @param atts the text attributes + * + * @return the encoded font description + */ + static String encodeFont(String name, Map atts) + { + String family = name; + if (family == null || family.equals("")) + family = (String) atts.get(TextAttribute.FAMILY); + if (family == null) + family = "SansSerif"; + + int size = 12; + Float sizeFl = (Float) atts.get(TextAttribute.SIZE); + if (sizeFl != null) + size = sizeFl.intValue(); + + int style = 0; + // Detect italic attribute. + Float posture = (Float) atts.get(TextAttribute.POSTURE); + if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR)) + style |= Font.ITALIC; + + // Detect bold attribute. + Float weight = (Float) atts.get(TextAttribute.WEIGHT); + if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0) + style |= Font.BOLD; + + return encodeFont(name, style, size); + } + + /** + * Encodes a font name + style + size specification into a X logical font + * description (XLFD) as described here: + * + * http://www.meretrx.com/e93/docs/xlfd.html + * + * This is implemented to look up the font description in the + * fonts.properties of this package. + * + * @param name the font name + * @param style the font style + * @param size the font size + * + * @return the encoded font description + */ + static String encodeFont(String name, int style, int size) + { + StringBuilder key = new StringBuilder(); + key.append(validName(name)); + key.append('.'); + switch (style) + { + case Font.BOLD: + key.append("bold"); + break; + case Font.ITALIC: + key.append("italic"); + break; + case (Font.BOLD | Font.ITALIC): + key.append("bolditalic"); + break; + case Font.PLAIN: + default: + key.append("plain"); + + } + + String protoType = fontProperties.getProperty(key.toString()); + int s = size; + return protoType.replaceFirst("%d", String.valueOf(s * 10)); + } + + /** + * Checks the specified font name for a valid font name. If the font name + * is not known, then this returns 'sansserif' as fallback. + * + * @param name the font name to check + * + * @return a valid font name + */ + static String validName(String name) + { + String retVal; + if (name.equalsIgnoreCase("sansserif") + || name.equalsIgnoreCase("serif") + || name.equalsIgnoreCase("monospaced") + || name.equalsIgnoreCase("dialog") + || name.equalsIgnoreCase("dialoginput")) + { + retVal = name.toLowerCase(); + } + else + { + retVal = "sansserif"; + } + return retVal; + } } diff --git a/libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java b/libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java index 439a2a7..74e47bc 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java @@ -137,4 +137,10 @@ public class XFramePeer throw new UnsupportedOperationException("Not yet implemented."); } + public Rectangle getBoundsPrivate() + { + // TODO: Implement this properly. + throw new InternalError("Not yet implemented"); + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphics.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphics.java deleted file mode 100644 index 134d7d3..0000000 --- a/libjava/classpath/gnu/java/awt/peer/x/XGraphics.java +++ /dev/null @@ -1,792 +0,0 @@ -/* XGraphics.java -- The Graphics implementation for X - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.java.awt.peer.x; - -import gnu.x11.Colormap; -import gnu.x11.Data; -import gnu.x11.Display; -import gnu.x11.Drawable; -import gnu.x11.GC; -import gnu.x11.Pixmap; -import gnu.x11.Point; -import gnu.x11.image.ZPixmap; - -import java.awt.AWTError; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.Toolkit; -import java.awt.Transparency; -import java.awt.image.BufferedImage; -import java.awt.image.ImageObserver; -import java.awt.image.ImageProducer; -import java.text.AttributedCharacterIterator; -import java.util.HashMap; - -public class XGraphics - extends Graphics - implements Cloneable -{ - - /** - * The X Drawable to draw on. - */ - private Drawable xdrawable; - - /** - * The X graphics context (GC). - */ - private GC xgc; - - /** - * The current translation. - */ - private int translateX; - private int translateY; - - /** - * The current clip. Possibly null. - */ - private Rectangle clip; - - /** - * The current font, possibly null. - */ - private Font font; - - /** - * The current foreground color, possibly null. - */ - private Color foreground; - - /** - * Indicates if this object has been disposed. - */ - private boolean disposed = false; - - // TODO: Workaround for limitation in current Escher. - private Pixmap.Format pixmapFormat; - private int imageByteOrder; - private int pixelByteCount; - - /** - * Creates a new XGraphics on the specified X Drawable. - * - * @param d the X Drawable for which we create the Graphics - */ - XGraphics(Drawable d) - { - xdrawable = d; - xgc = new GC(d); - translateX = 0; - translateY = 0; - clip = new Rectangle(0, 0, d.width, d.height); - - Display display = xdrawable.display; - pixmapFormat = display.default_pixmap_format; - imageByteOrder = display.image_byte_order; - pixelByteCount = pixmapFormat.bits_per_pixel () / 8; - } - - /** - * Creates an exact copy of this graphics context. - * - * @return an exact copy of this graphics context - */ - public Graphics create() - { - XGraphics copy = (XGraphics) clone(); - return copy; - } - - /** - * Translates the origin by (x, y). - */ - public void translate(int x, int y) - { - translateX += x; - translateY += y; - if (clip != null) - { - clip.x -= x; - clip.y -= y; - } - } - - /** - * Returns the current foreground color, possibly null. - * - * @return the current foreground color, possibly null - */ - public Color getColor() - { - return foreground; - } - - /** - * Sets the current foreground color. A null value doesn't - * change the current setting. - * - * @param c the foreground color to set - */ - public void setColor(Color c) - { - if (c != null) - { - XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit(); - HashMap colorMap = tk.colorMap; - gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c); - if (col == null) - { - Colormap map = xdrawable.display.default_colormap; - col = map.alloc_color (c.getRed() * 256, - c.getGreen() * 256, - c.getBlue() * 256); - colorMap.put(c, col); - } - xgc.set_foreground(col); - foreground = c; - } - } - - public void setPaintMode() - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public void setXORMode(Color color) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Returns the current font, possibly null. - * - * @return the current font, possibly null - */ - public Font getFont() - { - return font; - } - - /** - * Sets the font on the graphics context. A null value doesn't - * change the current setting. - * - * @param f the font to set - */ - public void setFont(Font f) - { - if (f != null) - { - XFontPeer xFontPeer = (XFontPeer) f.getPeer(); - xgc.set_font(xFontPeer.getXFont()); - font = f; - } - } - - /** - * Returns the font metrics for the specified font. - * - * @param font the font for which we want the font metrics - * - * @return the font metrics for the specified font - */ - public FontMetrics getFontMetrics(Font font) - { - if (font == null) - { - if (this.font == null) - setFont(new Font("Dialog", Font.PLAIN, 12)); - font = this.font; - } - XFontPeer xFontPeer = (XFontPeer) font.getPeer(); - return xFontPeer.getFontMetrics(font); - } - - /** - * Returns the bounds of the current clip. - * - * @return the bounds of the current clip - */ - public Rectangle getClipBounds() - { - return clip != null ? clip.getBounds() : null; - } - - /** - * Clips the current clip with the specified clip. - */ - public void clipRect(int x, int y, int width, int height) - { - if (clip == null) - { - clip = new Rectangle(x, y, width, height); - } - else - { - computeIntersection(x, y, width, height, clip); - } - // Update the X clip setting. - setXClip(clip.x, clip.y, clip.width, clip.height); - } - - /** - * Returns true when the specified rectangle intersects with - * the current clip, false otherwise. This is overridden to - * avoid unnecessary creation of Rectangles via getBounds(). - * - * @param x the x coordinate of the rectangle - * @param y the y coordinate of the rectangle - * @param w the width of the rectangle - * @param h the height of the rectangle - * - * @return true when the specified rectangle intersects with - * the current clip, false otherwise - */ - public boolean hitClip(int x, int y, int w, int h) - { - boolean hit; - if (clip == null) - { - hit = true; - } - else - { - // It's easier to determine if the rectangle lies outside the clip, - // so we determine that and reverse the result (if it's not completely - // outside, it most likely hits the clip rectangle). - int x2 = x + w; - int y2 = y + h; - int clipX2 = clip.x + clip.width; - int clipY2 = clip.y + clip.height; - boolean outside = (x < clip.x && x2 < clip.x) // Left. - || (x > clipX2 && x2 > clipX2) // Right. - || (y < clip.y && y2 < clip.y) // Top. - || (y > clipY2 && y2 > clipY2); // Bottom. - hit = ! outside; - } - return hit; - } - - public void setClip(int x, int y, int width, int height) - { - if (clip != null) - clip.setBounds(x, y, width, height); - else - clip = new Rectangle(x, y, width, height); - setXClip(clip.x, clip.y, clip.width, clip.height); - } - - /** - * Sets the clip on the X server GC. The coordinates are not yet translated, - * this will be performed by the X server. - * - * @param x the clip, X coordinate - * @param y the clip, Y coordinate - * @param w the clip, width - * @param h the clip, height - */ - private void setXClip(int x, int y, int w, int h) - { - gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] { - new gnu.x11.Rectangle(x, y, w, h) }; - xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.YX_BANDED); - } - - public Shape getClip() - { - // Return a copy here, so nobody can trash our clip. - return clip == null ? null : clip.getBounds(); - } - - /** - * Sets the current clip. - * - * @param c the clip to set - */ - public void setClip(Shape c) - { - if (c != null) - { - Rectangle b; - if (c instanceof Rectangle) - { - b = (Rectangle) c; - } - else - { - b = c.getBounds(); - } - clip.setBounds(b); - setXClip(b.x, b.y, b.width, b.height); - } - else - { - clip.setBounds(0, 0, xdrawable.width, xdrawable.height); - setXClip(0, 0, xdrawable.width, xdrawable.height); - } - } - - public void copyArea(int x, int y, int width, int height, int dx, int dy) - { - // Clip and translate src rectangle. - int srcX = Math.min(Math.max(x, clip.x), clip.x + clip.width) - + translateX; - int srcY = Math.min(Math.max(y, clip.y), clip.y + clip.height) - + translateY; - int srcWidth = Math.min(Math.max(x + width, clip.x), - clip.x + clip.width) - x; - int srcHeight = Math.min(Math.max(y + height, clip.y), - clip.y + clip.height) - y; - xdrawable.copy_area(xdrawable, xgc, srcX, srcY, srcWidth, srcHeight, - srcX + dx, srcY + dy); - } - - /** - * Draws a line from point (x1, y1) to point (x2, y2). - */ - public void drawLine(int x1, int y1, int x2, int y2) - { - //System.err.println("drawLine: " + (x1 + translateX) + ", " + ( y1 + translateY) + ", " + (x2 + translateX) + ", " + (y2 + translateY) + " on: " + xdrawable); - xdrawable.line(xgc, x1 + translateX, y1 + translateY, - x2 + translateX, y2 + translateY); - } - - /** - * Fills the specified rectangle. - */ - public void fillRect(int x, int y, int width, int height) - { - xdrawable.rectangle(xgc, x + translateX, y + translateY, - width, height, true); - } - - public void clearRect(int x, int y, int width, int height) - { - xgc.set_foreground(Color.WHITE.getRGB()); - xdrawable.rectangle(xgc, x, y, width, height, true); - if (foreground != null) - xgc.set_foreground(foreground.getRGB()); - } - - public void drawRoundRect(int x, int y, int width, int height, int arcWidth, - int arcHeight) - { - // Draw 4 lines. - int arcRadiusX = arcWidth / 2; - int arcRadiusY = arcHeight / 2; - drawLine(x + arcRadiusX, y, x + width - arcRadiusX, y); - drawLine(x, y + arcRadiusY, x, y + height - arcRadiusY); - drawLine(x + arcRadiusX, y + height, x + width - arcRadiusX, y + height); - drawLine(x + width, y + arcRadiusY, x + width, y + height - arcRadiusY); - - // Draw the 4 arcs at the corners. - // Upper left. - drawArc(x, y, arcWidth, arcHeight, 90, 90); - // Lower left. - drawArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90); - // Upper right. - drawArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90); - // Lower right. - drawArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight, - 270, 90); - } - - public void fillRoundRect(int x, int y, int width, int height, int arcWidth, - int arcHeight) - { - // Fill the 3 rectangles that make up the inner area. - int arcRadiusX = arcWidth / 2; - int arcRadiusY = arcHeight / 2; - // Left. - fillRect(x, y + arcRadiusY, arcRadiusX, height - arcHeight); - // Middle. - fillRect(x + arcRadiusX, y, width - arcWidth, height); - // Right. - fillRect(x + width - arcRadiusX, y + arcRadiusY, arcRadiusX, - height - arcHeight); - - // Fill the 4 arcs in the corners. - // Upper left. - fillArc(x, y, arcWidth, arcHeight, 90, 90); - // Lower left. - fillArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90); - // Upper right. - fillArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90); - // Lower right. - fillArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight, - 270, 90); - } - - public void drawOval(int x, int y, int width, int height) - { - xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, false); - } - - public void fillOval(int x, int y, int width, int height) - { - xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, true); - } - - public void drawArc(int x, int y, int width, int height, int arcStart, - int arcAngle) - { - xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, false); - } - - public void fillArc(int x, int y, int width, int height, int arcStart, - int arcAngle) - { - xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, true); - } - - public void drawPolyline(int[] xPoints, int[] yPoints, int npoints) - { - int numPoints = Math.min(xPoints.length, yPoints.length); - Point[] points = new Point[numPoints]; - // FIXME: Improve Escher API to accept arrays to avoid creation - // of many Point objects. - for (int i = 0; i < numPoints; i++) - points[i] = new Point(xPoints[i], yPoints[i]); - xdrawable.poly_line(xgc, points, Drawable.ORIGIN); - } - - public void drawPolygon(int[] xPoints, int[] yPoints, int npoints) - { - int numPoints = Math.min(xPoints.length, yPoints.length); - Point[] points = new Point[numPoints]; - // FIXME: Improve Escher API to accept arrays to avoid creation - // of many Point objects. - for (int i = 0; i < numPoints; i++) - points[i] = new Point(xPoints[i], yPoints[i]); - xdrawable.poly_line(xgc, points, Drawable.ORIGIN); - } - - public void fillPolygon(int[] xPoints, int[] yPoints, int npoints) - { - int numPoints = Math.min(xPoints.length, yPoints.length); - Point[] points = new Point[numPoints]; - // FIXME: Improve Escher API to accept arrays to avoid creation - // of many Point objects. - for (int i = 0; i < numPoints; i++) - points[i] = new Point(xPoints[i], yPoints[i]); - xdrawable.fill_poly(xgc, points, Drawable.COMPLEX, Drawable.ORIGIN); - } - - /** - * Draws the specified string at (x, y). - */ - public void drawString(String string, int x, int y) - { - if (disposed) - throw new AWTError("XGraphics already disposed"); - - xdrawable.text(xgc, x + translateX, y + translateY, string); - } - - public void drawString(AttributedCharacterIterator ci, int x, int y) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - /** - * Draws the specified image on the drawable at position (x,y). - */ - public boolean drawImage(Image image, int x, int y, ImageObserver observer) - { - if (image instanceof XImage) - { - XImage xim = (XImage) image; - Pixmap pm = xim.pixmap; - xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height, - x + translateX, y + translateY); - } - else if (image instanceof BufferedImage - && ((BufferedImage) image).getTransparency() != Transparency.OPAQUE) - { - BufferedImage bi = (BufferedImage) image; - int width = bi.getWidth(); - int height = bi.getHeight(); - Data img = xdrawable.image(x + translateX, y + translateY, - width, height, 0xFFFFFFFF, 2); - - // Compute line byte count. - int lineBitCount = width * pixmapFormat.bits_per_pixel (); - int rem = lineBitCount % pixmapFormat.scanline_pad (); - int linePadCount = lineBitCount / pixmapFormat.scanline_pad () - + (rem == 0 ? 0 : 1); - int lineByteCount = linePadCount * pixmapFormat.scanline_pad () / 8; - - // Composite source and destination pixel data. - int[] trgb = new int[3]; // The device rgb pixels. - for (int yy = 0; yy < height; yy++) - { - for (int xx = 0; xx < width; xx++) - { - getRGB(xx, yy, img, trgb, lineByteCount); - int srgb = bi.getRGB(xx, yy); - float alpha = ((srgb >> 24) & 0xff) / 256F; - float tAlpha = 1.F - alpha; - int red = (srgb >> 16) & 0xFF; - int green = (srgb >> 8) & 0xFF; - int blue = (srgb) & 0xFF; - trgb[0] = (int) (trgb[0] * tAlpha + red * alpha); - trgb[1] = (int) (trgb[1] * tAlpha + green * alpha); - trgb[2] = (int) (trgb[2] * tAlpha + blue * alpha); - setRGB(xx, yy, img, trgb, lineByteCount); - } - } - - // Now we have the transparent image composited onto the target - // Image, now we only must copy it to the Drawable. - ZPixmap pm = new ZPixmap(xdrawable.display); - pm.width = width; - pm.height = height; - pm.init(); - System.arraycopy(img.data, 32, pm.data, 0, img.data.length - 32); - xdrawable.put_image(xgc, pm, x + translateX, y + translateY); - } - else - { - // Pre-render the image into an XImage. - ImageProducer source = image.getSource(); - ImageConverter conv = new ImageConverter(); - source.startProduction(conv); - XImage xim = conv.getXImage(); - Pixmap pm = xim.pixmap; - xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height, - x + translateX, y + translateY); - } - return true; - } - - /** - * Helper method to work around limitation in the current Escher impl. - * - * @param x the x position - * @param y the y position - * @param img the image data - * @param rgb an 3-size array that holds the rgb values on method exit - */ - private void getRGB(int x, int y, Data img, int[] rgb, int lineByteCount) - { - // TODO: Does this also work on non-RGB devices? - int i = y * lineByteCount + pixelByteCount * x; - if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST) - {//if (i >= 5716-33) System.err.println("lbc: " + lineByteCount + ", " + pixelByteCount); - rgb[2] = img.data[32 + i]; - rgb[1] = img.data[32 + i + 1]; - rgb[0] = img.data[32 + i + 2]; - } - else - { // MSB_FIRST - rgb[0] = img.data[32 + i]; - rgb[1] = img.data[32 + i + 1]; - rgb[2] = img.data[32 + i + 2]; - } - - } - - /** - * Helper method to work around limitation in the current Escher impl. - * - * @param x the x position - * @param y the y position - * @param img the image data - * @param rgb an 3-size array that holds the rgb values on method exit - */ - private void setRGB(int x, int y, Data img, int[] rgb, int lineByteCount) - { - // TODO: Does this also work on non-RGB devices? - int i = y * lineByteCount + pixelByteCount * x; - if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST) - { - img.data[32 + i] = (byte) rgb[2]; - img.data[32 + i + 1] = (byte) rgb[1]; - img.data[32 + i + 2] = (byte) rgb[0]; - } - else - { // MSB_FIRST - img.data[32 + i] = (byte) rgb[0]; - img.data[32 + i + 1] = (byte) rgb[1]; - img.data[32 + i + 2] = (byte) rgb[2]; - } - } - - public boolean drawImage(Image image, int x, int y, int width, int height, - ImageObserver observer) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean drawImage(Image image, int x, int y, Color bgcolor, - ImageObserver observer) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean drawImage(Image image, int x, int y, int width, int height, - Color bgcolor, ImageObserver observer) - { - // FIXME: Implement this. - throw new UnsupportedOperationException("Not yet implemented"); - } - - public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, - int sx1, int sy1, int sx2, int sy2, - ImageObserver observer) - { - return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, - observer); - } - - public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, - int sx1, int sy1, int sx2, int sy2, Color bgcolor, - ImageObserver observer) - { - - // FIXME: What to do with bgcolor? - - // Scale the image. - int sw = image.getWidth(observer); - int sh = image.getHeight(observer); - double scaleX = Math.abs(dx2 - dx1) / (double) Math.abs(sx2 - sx1); - double scaleY = Math.abs(dy2 - dy1) / (double) Math.abs(sy2 - sy1); - Image scaled = image.getScaledInstance((int) (scaleX * sw), - (int) (scaleY * sh), - Image.SCALE_FAST); - - // Scaled source coordinates. - int sx1s = (int) (scaleX * Math.min(sx1, sx2)); - int sx2s = (int) (scaleX * Math.max(sx1, sx2)); - - // Temporarily clip to the target rectangle. - Rectangle old = clip; - clipRect(dx1, dy1, dx2 - dx1, dy2 - dy1); - - // Draw scaled image. - boolean res = drawImage(scaled, dx1 - sx1s, dy1 - sx2s, observer); - - // Reset clip. - setClip(old); - - return res; - } - - /** - * Frees any resources associated with this object. - */ - public void dispose() - { - if (! disposed) - { - xgc.free(); - xdrawable.display.flush(); - disposed = true; - } - } - - // Additional helper methods. - - /** - * Creates and returns an exact copy of this XGraphics. - */ - protected Object clone() - { - try - { - XGraphics copy = (XGraphics) super.clone(); - copy.xgc = xgc.copy(); - if (clip != null) - { - copy.clip = new Rectangle(clip); - copy.setXClip(clip.x, clip.y, clip.width, clip.height); - } - return copy; - } - catch (CloneNotSupportedException ex) - { - assert false; - } - return null; - } - - /** - * Computes the intersection between two rectangles and stores the result - * int the second rectangle. - * - * This method has been copied from {@link javax.swing.SwingUtilities}. - * - * @param x the x coordinate of the rectangle #1 - * @param y the y coordinate of the rectangle #1 - * @param w the width of the rectangle #1 - * @param h the height of the rectangle #1 - * @param rect the rectangle #2 and output rectangle - */ - private static void computeIntersection(int x, int y, int w, int h, - Rectangle rect) - { - int x2 = (int) rect.x; - int y2 = (int) rect.y; - int w2 = (int) rect.width; - int h2 = (int) rect.height; - - int dx = (x > x2) ? x : x2; - int dy = (y > y2) ? y : y2; - int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx); - int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy); - - if (dw >= 0 && dh >= 0) - rect.setBounds(dx, dy, dw, dh); - else - rect.setBounds(0, 0, 0, 0); - } - - -} diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java index 5dc79ff..73e780c 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java @@ -37,16 +37,23 @@ exception statement from your version. */ package gnu.java.awt.peer.x; +import java.awt.Color; import java.awt.Graphics; import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Toolkit; import java.awt.geom.AffineTransform; import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; import java.awt.image.Raster; +import java.util.HashMap; import gnu.java.awt.java2d.AbstractGraphics2D; +import gnu.java.awt.java2d.ScanlineCoverage; +import gnu.x11.Colormap; import gnu.x11.Drawable; import gnu.x11.GC; import gnu.x11.image.ZPixmap; @@ -70,6 +77,11 @@ public class XGraphics2D */ private boolean disposed; + /** + * The current foreground color, possibly null. + */ + private Color foreground; + XGraphics2D(Drawable d) { super(); @@ -80,31 +92,9 @@ public class XGraphics2D //setClip(new Rectangle(0, 0, xdrawable.width, xdrawable.height)); } - /** - * Draws a pixel in the target coordinate space using the specified color. - * - * @param x the x coordinate - * @param y the y coordinate - */ - protected void rawSetPixel(int x, int y) - { - xdrawable.point(xgc, x, y); - } - -// protected void rawFillPolygon(double[] xpoints, double[] ypoints, int npoints) -// { -// Point[] points = new Point[npoints]; -// for (int n = 0; n < npoints; n++) -// { -// points[n] = new Point((int) xpoints[n], (int) ypoints[n]); -// } -// xdrawable.fill_poly(xgc, points, Drawable.COMPLEX, Drawable.ORIGIN); -// xdrawable.display.flush(); -// } - protected void rawDrawLine(int x0, int y0, int x1, int y1) { - xdrawable.line(xgc, x0, y0, x1, y1); + xdrawable.segment(xgc, x0, y0, x1, y1); } protected void rawFillRect(int x, int y, int w, int h) @@ -112,17 +102,6 @@ public class XGraphics2D xdrawable.rectangle(xgc, x, y, w, h, true); } - protected void rawSetForeground(java.awt.Color c) - { - if (c != null) - xgc.set_foreground(c.getRGB()); - } - - protected void rawSetForeground(int r, int g, int b) - { - xgc.set_foreground( r << 16 | g << 8 | b ); - } - /** * Returns the color model of this Graphics object. * @@ -178,55 +157,6 @@ public class XGraphics2D return copy; } -// /** -// * Draws the specified image on the drawable at position (x,y). -// */ -// -// public boolean drawImage(Image image, int x, int y, ImageObserver observer) -// { -// AffineTransform transform = getTransform(); -// int translateX = (int) transform.getTranslateX(); -// int translateY = (int) transform.getTranslateY(); -// if (image instanceof XImage) -// { -// XImage xim = (XImage) image; -// Pixmap pm = xim.pixmap; -// xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height, -// x + translateX, y + translateY); -// } -// else if (image instanceof BufferedImage) -// { -// BufferedImage bufferedImage = (BufferedImage) image; -// Raster raster = bufferedImage.getData(); -// int w = bufferedImage.getWidth(); -// int h = bufferedImage.getHeight(); -// // Push data to X server. -// ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h, -// xdrawable.display.default_pixmap_format); -// System.err.println("data buffer length: " + zPixmap.data.length); -// int[] pixel = new int[4]; -// for (int tx = 0; tx < w; tx++) -// { -// for (int ty = 0; ty < h; ty++) -// { -// pixel = raster.getPixel(tx, ty, pixel); -//// System.err.print("r: " + pixel[0]); -//// System.err.print(", g: " + pixel[1]); -//// System.err.println(", b: " + pixel[2]); -// zPixmap.set_red(tx, ty, pixel[0]); -// zPixmap.set_green(tx, ty, pixel[1]); -// zPixmap.set_blue(tx, ty, pixel[2]); -// } -// } -// xdrawable.put_image(xgc, zPixmap, x, y); -// } -// else -// { -// throw new UnsupportedOperationException("Not yet implemented."); -// } -// return true; -// } -// public void setClip(Shape c) { super.setClip(c); @@ -287,9 +217,115 @@ public class XGraphics2D } } + public void renderScanline(int y, ScanlineCoverage c) + { + ScanlineCoverage.Iterator iter = c.iterate(); + float coverageAlpha = 0; + int maxCoverage = c.getMaxCoverage(); + Color old = getColor(); + Color col = getColor(); + if (col == null) + col = Color.BLACK; + while (iter.hasNext()) + { + ScanlineCoverage.Range range = iter.next(); + // TODO: Dumb implementation for testing. + coverageAlpha = range.getCoverage(); + if (coverageAlpha > 0) + { + int red = col.getRed(); + int green = col.getGreen(); + int blue = col.getBlue(); + if (coverageAlpha < c.getMaxCoverage()) + { + float alpha = coverageAlpha / maxCoverage; + red = 255 - (int) ((255 - red) * alpha); + green = 255 - (int) ((255 - green) * alpha); + blue = 255 - (int) ((255 - blue) * alpha); + } + xgc.set_foreground(red << 16 | green << 8 | blue); + int x0 = range.getXPos(); + int l = range.getLength(); + xdrawable.fill_rectangle(xgc, x0, y, l, 1); + } + } + if (old != null) + xgc.set_foreground(old.getRGB()); + } + + protected void fillScanline(int x0, int x1, int y) + { + xdrawable.segment(xgc, x0, y, x1, y); + } + + protected void fillScanlineAA(int x0, int x1, int y, int alpha) + { + //System.err.println("fillScanlineAA: " + x0 + ", " + x1 + ", " + y + ", " + alpha); + // FIXME: This is for testing only. + Color c = getColor(); + setColor(new Color(255-alpha, 255-alpha, 255-alpha)); + xdrawable.segment(xgc, x0, y, x1, y); + setColor(c); + } protected void init() { super.init(); } + + public void setPaint(Paint p) + { + super.setPaint(p); + if (p instanceof Color) + { + Color c = (Color) p; + XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit(); + HashMap colorMap = tk.colorMap; + gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c); + if (col == null) + { + Colormap map = xdrawable.display.default_colormap; + col = map.alloc_color (c.getRed() * 256, + c.getGreen() * 256, + c.getBlue() * 256); + colorMap.put(c, col); + } + xgc.set_foreground(col); + foreground = c; + } + } + + protected void fillShape(Shape s, boolean isFont) + { + synchronized (xdrawable.display) { + super.fillShape(s, isFont); + } + } + + protected boolean rawDrawImage(Image image, int x, int y, ImageObserver obs) + { + boolean ret; + if (image instanceof XImage) + { + XImage xImage = (XImage) image; + xdrawable.copy_area(xImage.pixmap, xgc, 0, 0, xImage.getWidth(obs), + xImage.getHeight(obs), x, y); + ret = true; + } + else if (image instanceof PixmapVolatileImage) + { + PixmapVolatileImage pvi = (PixmapVolatileImage) image; + xdrawable.copy_area(pvi.getPixmap(), xgc, 0, 0, pvi.getWidth(obs), + pvi.getHeight(obs), x, y); + ret = true; + } + else + { + ret = super.rawDrawImage(image, x, y, obs); + } + return ret; + } + + } + diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java index d6e66cb..11a9c96 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java @@ -39,11 +39,20 @@ package gnu.java.awt.peer.x; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; +import java.awt.Point; import java.awt.Rectangle; +import java.awt.Transparency; +import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.ComponentSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.SampleModel; import java.awt.image.VolatileImage; +import java.awt.image.WritableRaster; public class XGraphicsConfiguration extends GraphicsConfiguration @@ -63,26 +72,60 @@ public class XGraphicsConfiguration public BufferedImage createCompatibleImage(int w, int h) { - return new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + return createCompatibleImage(w, h, Transparency.OPAQUE); } - public VolatileImage createCompatibleVolatileImage(int w, int h) + public BufferedImage createCompatibleImage(int w, int h, int transparency) { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); + BufferedImage bi; + switch (transparency) + { + case Transparency.OPAQUE: + DataBuffer buffer = new ZPixmapDataBuffer(w, h); + SampleModel sm = new ComponentSampleModel(DataBuffer.TYPE_BYTE, w, h, + 4, w * 4, + new int[]{0, 1, 2, 3 }); + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); + ColorModel cm = new ComponentColorModel(cs, true, false, + Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); + WritableRaster raster = Raster.createWritableRaster(sm, buffer, + new Point(0, 0)); + bi = new BufferedImage(cm, raster, false, null); + break; + case Transparency.BITMASK: + case Transparency.TRANSLUCENT: + bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + break; + default: + throw new IllegalArgumentException("Illegal transparency: " + + transparency); + } + return bi; } - public VolatileImage createCompatibleVolatileImage(int width, int height, - int transparency) + public VolatileImage createCompatibleVolatileImage(int w, int h) { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); + return createCompatibleVolatileImage(w, h, Transparency.OPAQUE); } - public BufferedImage createCompatibleImage(int w, int h, int transparency) + public VolatileImage createCompatibleVolatileImage(int width, int height, + int transparency) { - // TODO: Implement this. - throw new UnsupportedOperationException("Not yet implemented."); + VolatileImage im; + switch (transparency) + { + case Transparency.OPAQUE: + im = new PixmapVolatileImage(width, height); + break; + case Transparency.BITMASK: + case Transparency.TRANSLUCENT: + throw new UnsupportedOperationException("Not yet implemented"); + default: + throw new IllegalArgumentException("Unknown transparency type: " + + transparency); + } + return im; } public ColorModel getColorModel() diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java index 6a020ec..eff5902 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java @@ -38,15 +38,12 @@ exception statement from your version. */ package gnu.java.awt.peer.x; import gnu.classpath.SystemProperties; -import gnu.java.net.local.LocalSocket; -import gnu.java.net.local.LocalSocketAddress; -import gnu.x11.Connection; import gnu.x11.Display; -import java.awt.AWTError; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; -import java.net.SocketException; +import java.lang.reflect.Constructor; +import java.net.Socket; /** * This class represents an X Display. The actual connection is established @@ -127,33 +124,21 @@ public class XGraphicsDevice || displayName.hostname.equals("")) && SystemProperties.getProperty("gnu.xawt.no_local_sockets") == null) { - // TODO: Is this 100% ok? - String sockPath = "/tmp/.X11-unix/X" + displayName.display_no; - LocalSocketAddress addr = new LocalSocketAddress(sockPath); - try + Socket socket = createLocalSocket(); + if (socket != null) { - if (XToolkit.DEBUG) - System.err.println("connecting to local socket: " - + sockPath); - LocalSocket socket = new LocalSocket(addr); display = new Display(socket, "localhost", displayName.display_no, displayName.screen_no); - display.connection.send_mode = Connection.ASYNCHRONOUS; - if (XToolkit.DEBUG) - System.err.println("connected to local socket"); } - catch (SocketException ex) - { - AWTError err = new AWTError("could not connect to X server"); - err.initCause(ex); - throw err; - } - } - else - { - display = new Display(displayName); } + + // The following happens when we are configured to use plain sockets, + // when the connection is probably remote or when we couldn't load + // the LocalSocket class stuff. + if (display == null) + display = new Display(displayName); + eventPump = new XEventPump(display); } return display; @@ -163,4 +148,36 @@ public class XGraphicsDevice { return eventPump; } + + /** + * Tries to load the LocalSocket class and initiate a connection to the + * local X server. + */ + private Socket createLocalSocket() + { + Socket socket = null; + try + { + // TODO: Is this 100% ok? + String sockPath = "/tmp/.X11-unix/X" + displayName.display_no; + Class localSocketAddressClass = + Class.forName("gnu.java.net.local.LocalSocketAddress"); + Constructor localSocketAddressConstr = + localSocketAddressClass.getConstructor(new Class[]{ String.class }); + Object addr = + localSocketAddressConstr.newInstance(new Object[]{ sockPath }); + Class localSocketClass = + Class.forName("gnu.java.net.local.LocalSocket"); + Constructor localSocketConstructor = + localSocketClass.getConstructor(new Class[]{localSocketAddressClass}); + Object localSocket = + localSocketConstructor.newInstance(new Object[]{ addr }); + socket = (Socket) localSocket; + } + catch (Exception ex) + { + // Whatever goes wrong here, we return null. + } + return socket; + } } diff --git a/libjava/classpath/gnu/java/awt/peer/x/XImage.java b/libjava/classpath/gnu/java/awt/peer/x/XImage.java index b9e9936..7d4636b 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XImage.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XImage.java @@ -86,7 +86,7 @@ public class XImage */ public Graphics getGraphics() { - XGraphics g = new XGraphics(pixmap); + XGraphics2D g = new XGraphics2D(pixmap); return g; } diff --git a/libjava/classpath/gnu/java/awt/peer/x/XLightweightPeer.java b/libjava/classpath/gnu/java/awt/peer/x/XLightweightPeer.java deleted file mode 100644 index 2613d84..0000000 --- a/libjava/classpath/gnu/java/awt/peer/x/XLightweightPeer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* XLightweightPeer.java -- A lightweight peer for X - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.java.awt.peer.x; - -import java.awt.Component; -import java.awt.peer.LightweightPeer; - -import gnu.java.awt.peer.swing.SwingContainerPeer; - -public class XLightweightPeer - extends SwingContainerPeer - implements LightweightPeer -{ - - XLightweightPeer(Component c) - { - super(c); - init(c, null); - } -} diff --git a/libjava/classpath/gnu/java/awt/peer/x/XToolkit.java b/libjava/classpath/gnu/java/awt/peer/x/XToolkit.java index a286fd6..0818632 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XToolkit.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XToolkit.java @@ -44,7 +44,6 @@ import java.awt.Canvas; import java.awt.Checkbox; import java.awt.CheckboxMenuItem; import java.awt.Choice; -import java.awt.Component; import java.awt.Dialog; import java.awt.Dimension; import java.awt.EventQueue; @@ -69,6 +68,8 @@ import java.awt.TextArea; import java.awt.TextField; import java.awt.Transparency; import java.awt.Window; +import java.awt.Dialog.ModalExclusionType; +import java.awt.Dialog.ModalityType; import java.awt.datatransfer.Clipboard; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.peer.DragSourceContextPeer; @@ -88,7 +89,6 @@ import java.awt.peer.FileDialogPeer; import java.awt.peer.FontPeer; import java.awt.peer.FramePeer; import java.awt.peer.LabelPeer; -import java.awt.peer.LightweightPeer; import java.awt.peer.ListPeer; import java.awt.peer.MenuBarPeer; import java.awt.peer.MenuItemPeer; @@ -179,16 +179,16 @@ public class XToolkit */ public ClasspathFontPeer getClasspathFontPeer(String name, Map attrs) { - String canonical = XFontPeer.encodeFont(name, attrs); + String canonical = XFontPeer2.encodeFont(name, attrs); ClasspathFontPeer font; if (!fontCache.containsKey(canonical)) { String graphics2d = SystemProperties.getProperty("gnu.xawt.graphics2d"); - if (graphics2d != null && graphics2d.equals("gl")) + //if (graphics2d != null && graphics2d.equals("gl")) font = new XFontPeer2(name, attrs); - else - font = new XFontPeer(name, attrs); +// else +// font = new XFontPeer(name, attrs); fontCache.put(canonical, font); } else @@ -601,8 +601,20 @@ public class XToolkit return (XGraphicsDevice) env.getDefaultScreenDevice(); } - protected LightweightPeer createComponent(Component c) + @Override + public boolean isModalExclusionTypeSupported + (Dialog.ModalExclusionType modalExclusionType) { - return new XLightweightPeer(c); + // TODO: Implement properly. + return false; } + + @Override + public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) + { + // TODO: Implement properly. + return false; + } + + } diff --git a/libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java index 28cc5a5..10d1e968 100644 --- a/libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java @@ -43,12 +43,16 @@ import java.awt.EventQueue; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.PaintEvent; import java.awt.event.WindowEvent; +import java.awt.image.VolatileImage; import gnu.x11.Window; import gnu.x11.event.Event; @@ -135,12 +139,22 @@ public class XWindowPeer */ public Graphics getGraphics() { - return new XGraphics(xwindow); + return new XGraphics2D(xwindow); } public Image createImage(int w, int h) { - return new XImage(w, h); + // FIXME: Should return a buffered image. + return createVolatileImage(w, h); + } + + @Override + public VolatileImage createVolatileImage(int width, int height) + { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice gd = ge.getDefaultScreenDevice(); + GraphicsConfiguration gc = gd.getDefaultConfiguration(); + return gc.createCompatibleVolatileImage(width, height); } /** @@ -168,6 +182,9 @@ public class XWindowPeer new Rectangle(0, 0, w.getWidth(), w.getHeight()))); + Graphics g = getGraphics(); + g.clearRect(0, 0, awtComponent.getWidth(), awtComponent.getHeight()); + g.dispose(); // // Reset input selection. // atts.set_override_redirect(false); // xwindow.change_attributes(atts); @@ -240,7 +257,7 @@ public class XWindowPeer */ public FontMetrics getFontMetrics(Font font) { - XFontPeer fontPeer = (XFontPeer) font.getPeer(); + XFontPeer2 fontPeer = (XFontPeer2) font.getPeer(); return fontPeer.getFontMetrics(font); } diff --git a/libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java b/libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java new file mode 100644 index 0000000..8043c5b --- /dev/null +++ b/libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java @@ -0,0 +1,62 @@ +package gnu.java.awt.peer.x; + +import gnu.x11.Display; +import gnu.x11.image.ZPixmap; + +import java.awt.GraphicsEnvironment; +import java.awt.image.DataBuffer; + +/** + * A DataBuffer implementation that is based on a ZPixmap. This is used + * as backing store for BufferedImages. + */ +class ZPixmapDataBuffer + extends DataBuffer +{ + + /** + * The backing ZPixmap. + */ + private ZPixmap zpixmap; + + /** + * Creates a new ZPixmapDataBuffer with a specified width and height. + * + * @param d the X display + * @param w the width + * @param h the height + */ + ZPixmapDataBuffer(int w, int h) + { + super(TYPE_BYTE, w * h * 3); // TODO: Support non-24-bit-resolutions. + GraphicsEnvironment env = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice(); + Display d = dev.getDisplay(); + zpixmap = new ZPixmap(d, w, h, d.default_pixmap_format); + } + + /** + * Creates a ZPixmapDataBuffer from an existing ZPixmap. + * + * @param zpixmap the ZPixmap to wrap + */ + ZPixmapDataBuffer(ZPixmap zpixmap) + { + super(TYPE_BYTE, zpixmap.get_data_length()); + this.zpixmap = zpixmap; + } + + @Override + public int getElem(int bank, int i) + { + return 0xff & zpixmap.get_data_element(i); + } + + @Override + public void setElem(int bank, int i, int val) + { + zpixmap.set_data_element(i, (byte) val); + } + +} diff --git a/libjava/classpath/gnu/java/math/Fixed.java b/libjava/classpath/gnu/java/math/Fixed.java index e0284c3..ed4150b 100644 --- a/libjava/classpath/gnu/java/math/Fixed.java +++ b/libjava/classpath/gnu/java/math/Fixed.java @@ -109,6 +109,19 @@ public final class Fixed } /** + * Truncates the number so that only the digits after the point are left. + * + * @param n the number of digits + * @param a the fixed point value + * + * @return the truncated value + */ + public static int trunc(int n, int a) + { + return a & (0xFFFFFFFF >>> 32 - n); + } + + /** * Returns the round value of a fixed point value a with * the n digits. * diff --git a/libjava/classpath/gnu/java/net/loader/URLLoader.java b/libjava/classpath/gnu/java/net/loader/URLLoader.java index 5228bca..5b9b674 100644 --- a/libjava/classpath/gnu/java/net/loader/URLLoader.java +++ b/libjava/classpath/gnu/java/net/loader/URLLoader.java @@ -42,6 +42,7 @@ import java.net.URL; import java.net.URLClassLoader; import java.net.URLStreamHandlerFactory; import java.security.CodeSource; +import java.security.cert.Certificate; import java.util.ArrayList; import java.util.jar.Manifest; @@ -95,7 +96,7 @@ public abstract class URLLoader this.baseURL = baseURL; this.factory = factory; this.cache = cache; - this.noCertCodeSource = new CodeSource(overrideURL, null); + this.noCertCodeSource = new CodeSource(overrideURL, (Certificate[]) null); } /** diff --git a/libjava/classpath/gnu/java/nio/charset/ISO_8859_1.java b/libjava/classpath/gnu/java/nio/charset/ISO_8859_1.java index 2a3073a..5582895 100644 --- a/libjava/classpath/gnu/java/nio/charset/ISO_8859_1.java +++ b/libjava/classpath/gnu/java/nio/charset/ISO_8859_1.java @@ -71,8 +71,12 @@ final class ISO_8859_1 extends Charset /* These names are provided by * http://oss.software.ibm.com/cgi-bin/icu/convexp?s=ALL */ - "ISO8859_1", "ISO_8859_1", "ibm-819", "ISO_8859-1:1987", - "819" + "ISO8859_1", + "ISO_8859_1", + "ibm-819", + "ISO_8859-1:1987", + "819", + "ISO8859-1" }); } diff --git a/libjava/classpath/gnu/java/security/Engine.java b/libjava/classpath/gnu/java/security/Engine.java index 44318af..8549192 100644 --- a/libjava/classpath/gnu/java/security/Engine.java +++ b/libjava/classpath/gnu/java/security/Engine.java @@ -146,7 +146,7 @@ public final class Engine throw new IllegalArgumentException("Constructor's parameters MUST NOT be null"); Enumeration enumer = provider.propertyNames(); - String key; + String key = null; String alias; int count = 0; boolean algorithmFound = false; @@ -193,7 +193,7 @@ public final class Engine Class clazz = null; ClassLoader loader = provider.getClass().getClassLoader(); Constructor constructor = null; - String className = provider.getProperty(service + "." + algorithm); + String className = provider.getProperty(key); sb.append("Class [").append(className).append("] for algorithm [") .append(algorithm).append("] of type [").append(service) .append("] from provider [").append(provider).append("] "); -- cgit v1.1