diff options
author | rolfwr <rolfwr@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-10-22 17:46:09 +0000 |
---|---|---|
committer | rolfwr <rolfwr@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-10-22 17:46:09 +0000 |
commit | e2d342dffa63aea98643515fd3b8c782ee8bd15e (patch) | |
tree | 1165199489e8bc851f2bb5c11ff0228f3667453e /libjava/gnu/awt | |
parent | cfed8d62a245d6113c86f79ffb2e4f09b2becc8d (diff) | |
download | gcc-e2d342dffa63aea98643515fd3b8c782ee8bd15e.tar.gz |
* Makefile.am: Added rules for libgcjx library.
* Makefile.in: Rebuilt.
* configure.in: Added check for X.
* configure: Rebuilt.
* gnu/awt/LightweightRedirector.java: New file.
* gnu/awt/j2d/AbstractGraphicsState.java: New file.
* gnu/awt/j2d/DirectRasterGraphics.java: New file.
* gnu/awt/j2d/Graphics2DImpl.java: New file.
* gnu/awt/j2d/IntegerGraphicsState.java: New file.
* gnu/awt/j2d/MappedRaster.java: New file.
* gnu/awt/xlib/XCanvasPeer.java: New file.
* gnu/awt/xlib/XEventLoop.java: New file.
* gnu/awt/xlib/XEventQueue.java: New file.
* gnu/awt/xlib/XFontMetrics.java: New file.
* gnu/awt/xlib/XFramePeer.java: New file.
* gnu/awt/xlib/XGraphics.java: New file.
* gnu/awt/xlib/XGraphicsConfiguration.java: New file.
* gnu/awt/xlib/XPanelPeer.java: New file.
* gnu/awt/xlib/XToolkit.java: New file.
* gnu/gcj/xlib/Clip.java: New file.
* gnu/gcj/xlib/Colormap.java: New file.
* gnu/gcj/xlib/Display.java: New file.
* gnu/gcj/xlib/Drawable.java: New file.
* gnu/gcj/xlib/Font.java: New file.
* gnu/gcj/xlib/GC.java: New file.
* gnu/gcj/xlib/Pixmap.java: New file.
* gnu/gcj/xlib/Screen.java: New file.
* gnu/gcj/xlib/Visual.java: New file.
* gnu/gcj/xlib/WMSizeHints.java: New file.
* gnu/gcj/xlib/Window.java: New file.
* gnu/gcj/xlib/WindowAttributes.java: New file.
* gnu/gcj/xlib/XAnyEvent.java: New file.
* gnu/gcj/xlib/XButtonEvent.java: New file.
* gnu/gcj/xlib/XColor.java: New file.
* gnu/gcj/xlib/XConfigureEvent.java: New file.
* gnu/gcj/xlib/XConnectException.java: New file.
* gnu/gcj/xlib/XEvent.java: New file.
* gnu/gcj/xlib/XException.java: New file.
* gnu/gcj/xlib/XExposeEvent.java: New file.
* gnu/gcj/xlib/XID.java: New file.
* gnu/gcj/xlib/XImage.java: New file.
* gnu/gcj/xlib/XUnmapEvent.java: New file.
* gnu/gcj/xlib/natClip.cc: New file.
* gnu/gcj/xlib/natColormap.cc: New file.
* gnu/gcj/xlib/natDisplay.cc: New file.
* gnu/gcj/xlib/natDrawable.cc: New file.
* gnu/gcj/xlib/natFont.cc: New file.
* gnu/gcj/xlib/natGC.cc: New file.
* gnu/gcj/xlib/natPixmap.cc: New file.
* gnu/gcj/xlib/natScreen.cc: New file.
* gnu/gcj/xlib/natVisual.cc: New file.
* gnu/gcj/xlib/natWMSizeHints.cc: New file.
* gnu/gcj/xlib/natWindow.cc: New file.
* gnu/gcj/xlib/natWindowAttributes.cc: New file.
* gnu/gcj/xlib/natXAnyEvent.cc: New file.
* gnu/gcj/xlib/natXButtonEvent.cc: New file.
* gnu/gcj/xlib/natXColor.cc: New file.
* gnu/gcj/xlib/natXConfigureEvent.cc: New file.
* gnu/gcj/xlib/natXException.cc: New file.
* gnu/gcj/xlib/natXExposeEvent.cc: New file.
* gnu/gcj/xlib/natXImage.cc: New file.
* gnu/gcj/xlib/natXUnmapEvent.cc: New file.
* java/awt/EventDispatchThread.java: Start thead on creation.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37005 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/gnu/awt')
-rw-r--r-- | libjava/gnu/awt/LightweightRedirector.java | 183 | ||||
-rw-r--r-- | libjava/gnu/awt/j2d/AbstractGraphicsState.java | 128 | ||||
-rw-r--r-- | libjava/gnu/awt/j2d/DirectRasterGraphics.java | 82 | ||||
-rw-r--r-- | libjava/gnu/awt/j2d/Graphics2DImpl.java | 454 | ||||
-rw-r--r-- | libjava/gnu/awt/j2d/IntegerGraphicsState.java | 409 | ||||
-rw-r--r-- | libjava/gnu/awt/j2d/MappedRaster.java | 72 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XCanvasPeer.java | 388 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XEventLoop.java | 268 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XEventQueue.java | 34 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XFontMetrics.java | 47 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XFramePeer.java | 174 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XGraphics.java | 279 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XGraphicsConfiguration.java | 367 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XPanelPeer.java | 52 | ||||
-rw-r--r-- | libjava/gnu/awt/xlib/XToolkit.java | 333 |
15 files changed, 3270 insertions, 0 deletions
diff --git a/libjava/gnu/awt/LightweightRedirector.java b/libjava/gnu/awt/LightweightRedirector.java new file mode 100644 index 00000000000..a0ea7bcff4b --- /dev/null +++ b/libjava/gnu/awt/LightweightRedirector.java @@ -0,0 +1,183 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt; + +import java.awt.AWTEvent; +import java.awt.AWTError; +import java.awt.Component; +import java.awt.Container; +import java.awt.event.MouseEvent; +import java.awt.event.InputEvent; + +/** + * Encapsulates the logic required to dispatch events to the correct + * component in a component tree that may contain lightweight + * components. Toolkits typically only identify heavyweight components + * as the source of events. This class redirects the events to the + * appropriate lightweight children of the heavyweight component. + */ +public class LightweightRedirector +{ + final static int LAST_BUTTON_NUMBER = 3; + + /* We sacrifice one array element to allow the button number to + match the index of this array. */ + Component[] releaseTargets = new Component[LAST_BUTTON_NUMBER+1]; + + /** + * + * Modifies or replaces the given event with an event that has been + * properly redirected. State of button presses are kept so that + * button releases can be redirected to the same component as the + * button press. It is required that all events are sent through + * this method in chronological order. + */ + public AWTEvent redirect(AWTEvent event) + { + if (event instanceof MouseEvent) + return redirectMouse((MouseEvent) event); + + /* In case we don't know how to redirect the event, simply return + the event unchanged. */ + return event; + } + + MouseEvent redirectMouse(MouseEvent event) + { + int button = getButtonNumber(event); + int id = event.getID(); + + Component heavySource = (Component) event.getSource(); + Component source = heavySource; + int x = event.getX(); + int y = event.getY(); + + if (id == MouseEvent.MOUSE_RELEASED) + { + Component target = releaseTargets[button]; + + if (target != null) + { + releaseTargets[button] = null; + source = target; + + Component child = source; + while (child != heavySource) + { + x -= child.getX(); + y -= child.getY(); + child = child.getParent(); + if (child == null) + System.err.println("warning, orphaned release target"); + } + } + } + else + { + /* Find real component, and adjust source, x and y + accordingly. */ + + while (true) + { + Component parent = source; + + Component child = parent.getComponentAt(x, y); + + if (parent == child) + break; + + // maybe ignoring would be better? + if (child == null) + { + String msg = "delivered event not within component. " + + "Heavyweight source was " + heavySource + ". " + + "Component was " + parent; + throw new AWTError(msg); + } + if (child.isLightweight()) + { + // descend down to child + source = child; + x -= child.getX(); + y -= child.getY(); + } + else + { + System.err.println("warning: event delivered to wrong " + + "heavyweight component. Was " + + "delivered to " + source + ". " + + "Should have been delivered to " + + child + ". Maybe the native window " + + "system is bubbling events up the " + + "containment hierarchy."); + break; + } + } + + /* ensure that the release event is delivered to the same + component as the press event. For most toolkits this is + only necessary for lightweight components, since the + underlying windowing system takes care of its heavyweight + components. */ + if (id == MouseEvent.MOUSE_PRESSED) + releaseTargets[button] = source; + } + + + if (source == heavySource) + return event; // no change in event + + // print warning for heavyweights + /* this warning can safely be removed if a toolkit that + needs heavyweight redirection support is ever created. */ + if (!source.isLightweight()) + System.err.println("warning: redirecting to heavyweight"); + + MouseEvent redirected = new MouseEvent(source, event.getID(), + event.getWhen(), + event.getModifiers(), + x, y, + event.getClickCount(), + event.isPopupTrigger()); + + return redirected; + } + + /** + * Identifies the button number for an input event. + * + * @returns the button number, or 0 if no button modifier was set + * for the event. + */ + int getButtonNumber(InputEvent event) + { + int modifiers = event.getModifiers(); + + modifiers &= + InputEvent.BUTTON1_MASK | + InputEvent.BUTTON2_MASK | + InputEvent.BUTTON3_MASK; + + switch (modifiers) + { + case InputEvent.BUTTON1_MASK: + return 1; + case InputEvent.BUTTON2_MASK: + return 2; + case InputEvent.BUTTON3_MASK: + return 3; + case 0: + return 0; + + default: + System.err.println("FIXME: multibutton event"); + return 0; + } + } +} diff --git a/libjava/gnu/awt/j2d/AbstractGraphicsState.java b/libjava/gnu/awt/j2d/AbstractGraphicsState.java new file mode 100644 index 00000000000..e3b3ec61599 --- /dev/null +++ b/libjava/gnu/awt/j2d/AbstractGraphicsState.java @@ -0,0 +1,128 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.j2d; + +import java.awt.Color; +import java.awt.Image; +import java.awt.Shape; +import java.awt.Rectangle; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.image.ImageObserver; + +/** + * Base class for graphics state objects (State pattern, GOF book) + * that represents the current pipeline configuration. The Graphics2D + * object forwards most of the requests to the state object. The + * Graphics2D object itself only administers properties that are not + * specific for a certain state. + */ +public abstract class AbstractGraphicsState implements Cloneable +{ + Graphics2DImpl frontend; + + public void setFrontend(Graphics2DImpl frontend) + { + this.frontend = frontend; + } + + public void dispose() + { + frontend = null; + } + + // -------- Graphics methods: + + public abstract void setColor(Color color); + + public abstract void setPaintMode(); + + public abstract void setXORMode(Color altColor); + + public abstract void setFont(Font font); + + public abstract FontMetrics getFontMetrics(Font font); + + public abstract void setClip(Shape clip); + + public abstract Shape getClip(); + public abstract Rectangle getClipBounds(); + + public abstract void copyArea(int x, int y, + int width, int height, + int dx, int dy); + + public abstract void drawLine(int x1, int y1, + int x2, int y2); + + public abstract void fillRect(int x, int y, + int width, int height); + + public abstract void clearRect(int x, int y, + int width, int height); + + public abstract void drawRoundRect(int x, int y, + int width, int height, + int arcWidth, int arcHeight); + + public abstract void fillRoundRect(int x, int y, + int width, int height, + int arcWidth, int arcHeight); + + public abstract void drawOval(int x, int y, + int width, int height); + + public abstract void fillOval(int x, int y, + int width, int height); + + public abstract void drawArc(int x, int y, + int width, int height, + int startAngle, int arcAngle); + + public abstract void fillArc(int x, int y, + int width, int height, + int startAngle, int arcAngle); + + public abstract void drawPolyline(int[] xPoints, int[] yPoints,int nPoints); + + public abstract void drawPolygon(int[] xPoints, int[] yPoints, int nPoints); + + public abstract void fillPolygon(int[] xPoints, int[] yPoints, int nPoints); + + public abstract boolean drawImage(Image image, int x, int y, + ImageObserver observer); + + + // -------- Graphics2D methods: + + public abstract void draw(Shape shape); + + public abstract void fill(Shape shape); + + public abstract boolean hit(Rectangle rect, Shape text, boolean onStroke); + + public abstract void drawString(String text, int x, int y); + + public abstract void drawString(String text, float x, float y); + + public abstract void translate(int x, int y); + + public abstract void translate(double tx, double ty); + + public abstract void rotate(double theta); + + public abstract void rotate(double theta, double x, double y); + + public abstract void scale(double scaleX, double scaleY); + + public abstract void shear(double shearX, double shearY); +} diff --git a/libjava/gnu/awt/j2d/DirectRasterGraphics.java b/libjava/gnu/awt/j2d/DirectRasterGraphics.java new file mode 100644 index 00000000000..6bbdbd1d23e --- /dev/null +++ b/libjava/gnu/awt/j2d/DirectRasterGraphics.java @@ -0,0 +1,82 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.j2d; + +import java.awt.Color; +import java.awt.Image; +import java.awt.Shape; +import java.awt.Rectangle; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.image.Raster; +import java.awt.image.ImageObserver; + +/** + * Interface for a simple pixel based backend graphics object that + * does not handle translation/transforms, curves, nor advanced + * compositing. + */ +public interface DirectRasterGraphics extends Cloneable +{ + public void dispose(); + + public void setColor(Color color); + + public void setPaintMode(); + + public void setXORMode(Color altColor); + + public void setFont(Font font); + + public FontMetrics getFontMetrics(Font font); + + // supports rects, multi-rects and polygons + public void setClip(Shape clip); + + public void copyArea(int x, int y, int width, int height, + int dx, int dy); + + public void drawLine(int x1, int y1, int x2, int y2); + + public void drawRect(int x, int y, int width, int height); + + public void fillRect(int x, int y, int width, int height); + + public void drawArc(int x, int y, int width, int height, + int startAngle, int arcAngle); + + public void fillArc(int x, int y, int width, int height, + int startAngle, int arcAngle); + + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints); + + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints); + + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints); + + public void drawString(String str, int x, int y); + + public boolean drawImage(Image image, int x, int y, + ImageObserver observer); + + /** + * Map the data for screen pixels in the requested bounds to a + * raster object. This gives read/write access to the screen + * pixels, allowing neat alpha and composite tricks. + */ + public MappedRaster mapRaster(Rectangle bounds); + + /** + * Detach previously mapped pixel data from a raster object. + */ + public void unmapRaster(MappedRaster mappedRaster); +} diff --git a/libjava/gnu/awt/j2d/Graphics2DImpl.java b/libjava/gnu/awt/j2d/Graphics2DImpl.java new file mode 100644 index 00000000000..7c08295c027 --- /dev/null +++ b/libjava/gnu/awt/j2d/Graphics2DImpl.java @@ -0,0 +1,454 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.j2d; + +import java.awt.Color; +import java.awt.Image; +import java.awt.Shape; +import java.awt.Rectangle; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Paint; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.ImageObserver; + +/** + * Delegates almost all work to a state object, that allows us to + * hot-swap rendering strategies based on state changes inflicted on + * this Graphics object. This class keeps track of properties that are + * not affected by the state, (such as clip shape, + * foreground/background color, font, etc.). + * + * <p>The far front-end of the rendering pipeline consists of the + * Graphics2D API. In the far back-end, lies the native graphics + * libraries. In most cases the native graphics libraries only have + * direct support for a subset of the properties of Graphics2D. To + * make up missing features in the native graphics libraries, the + * pipeline between the front-end and the back-end need to translate + * drawing request to primitive operations that are supported by the + * back-end. E.g. for X11, drawing a straight line will translate to + * an XDrawLine, drawing a bezier curve will trigger flattening of the + * curve and will result in a call to XDrawLines. + * + * <p>This is the basic strategy for the rendering pipeline: Whenever + * a graphics property change occurs, that causes the current pipeline + * to be insufficient, amend or replace parts of the pipeline so that + * the pipeline will once again be able to translate requests to the + * set of primitives supported by the native graphics library. + * + * <p>Most graphics libraries share common subsets of + * functionality. To be able to reuse pieces of the rendering pipeline + * for several backends, we define interfaces that describe subsets of + * characteristics supported by the backends. A wrapper for the native + * library can implement several interfaces to describe its range of + * functionality. + * + * <p>Typically, most painting is done with a graphics object with + * simple properties. Unless one is using a complex Look & Feel, the + * painting of Swing components will never require affine transforms, + * alpha blending, non-rectangular clipping, etc. When graphics + * objects are created, they start off in a state where all the + * properties are simple. Most graphics objects experience only + * trivial property changes, and never leave this simple state. It is + * therefore wise to ensure that the rendering pipeline for this + * initial state is lean and as much as possible plugs directly into + * the backend. + * + * <p>The initial state for graphics object of most raster displays + * would call for two levels of indirection: + * + * <pre> + * Graphics2D object ---> IntegerGraphicsState ---> DirectRasterGraphics + * </pre> + */ +public class Graphics2DImpl extends Graphics2D implements Cloneable +{ + GraphicsConfiguration config; + + AbstractGraphicsState state; + + Color fg; + Color bg; + + Font font; + + public Graphics2DImpl(GraphicsConfiguration config) + { + this.config = config; + } + + public void setState(AbstractGraphicsState state) + { + this.state = state; + this.state.setFrontend(this); + } + + public Object clone() + { + Graphics2DImpl gfxCopy = (Graphics2DImpl) super.clone(); + AbstractGraphicsState stateCopy = + (AbstractGraphicsState) state.clone(); + gfxCopy.setState(stateCopy); + + return gfxCopy; + } + + + // -------- Graphics methods: + + public Graphics create() + { + Graphics2DImpl gfxCopy = (Graphics2DImpl) clone(); + return gfxCopy; + } + + public Color getColor() + { + return fg; + } + + public void setColor(Color color) + { + fg = color; + state.setColor(color); + } + + public void setPaintMode() + { + state.setPaintMode(); + } + + public void setXORMode(Color altColor) + { + state.setXORMode(altColor); + } + + public Font getFont() + { + return font; + } + + public void setFont(Font font) + { + this.font = font; + state.setFont(font); + } + + public FontMetrics getFontMetrics(Font font) + { + return state.getFontMetrics(font); + } + + public Rectangle getClipBounds() + { + return state.getClipBounds(); + } + + public void clipRect(int x, int y, int width, int height) + { + Shape clip = state.getClip(); + if (clip instanceof Rectangle) + { + Rectangle clipRect = (Rectangle) clip; + clip = clipRect.intersection(new Rectangle(x, y, width, height)); + setClip(clip); + return; + } + + String msg = + "intersecting current clip shape " + clip + " with new rectangle " + + "has not been implemented yet"; + throw new UnsupportedOperationException(msg); + } + + public void setClip(int x, int y, int width, int height) + { + Rectangle clip = new Rectangle(x, y, width, height); + setClip(clip); + } + + public Shape getClip() + { + return state.getClip(); + } + + public void setClip(Shape clip) + { + state.setClip(clip); + } + + public void copyArea(int x, int y, int width, int height, + int dx, int dy) + { + state.copyArea(x, y, width, height, dx, dy); + } + + public void drawLine(int x1, int y1, int x2, int y2) + { + state.drawLine(x1, y1, x2, y2); + } + + public void fillRect(int x, int y, int width, int height) + { + state.fillRect(x, y, width, height); + } + + public void clearRect(int x, int y, int width, int height) + { + state.clearRect(x, y, width, height); + } + + public void drawRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight) + { + state.drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + public void fillRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight) + { + state.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + public void drawOval(int x, int y, int width, int height) + { + state.drawOval(x, y, width, height); + } + + public void fillOval(int x, int y, int width, int height) + { + state.fillOval(x, y, width, height); + } + + public void drawArc(int x, int y, int width, int height, + int startAngle, int arcAngle) + { + state.drawArc(x, y, width, height, startAngle, arcAngle); + } + + public void fillArc(int x, int y, int width, int height, + int startAngle, int arcAngle) + { + state.fillArc(x, y, width, height, startAngle, arcAngle); + } + + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) + { + state.drawPolyline(xPoints, yPoints, nPoints); + } + + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) + { + state.drawPolygon(xPoints, yPoints, nPoints); + } + + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) + { + state.fillPolygon(xPoints, yPoints, nPoints); + } + + public boolean drawImage(Image image, int x, int y, + ImageObserver observer) + { + return state.drawImage(image, x, y, observer); + } + + public boolean drawImage(Image img, int x, int y, + int width, int height, + ImageObserver observer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public boolean drawImage(Image img, int x, int y, Color bgcolor, + ImageObserver observer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public boolean drawImage(Image img, int x, int y, + int width, int height, Color bgcolor, + ImageObserver observer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public boolean drawImage(Image img, + int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + ImageObserver observer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public boolean drawImage(Image img, + int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, + Color bgcolor, ImageObserver observer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void dispose() + { + AbstractGraphicsState lState = state; + + state = null; + config = null; + font = null; + fg = null; + bg = null; + + if (lState != null) + lState.dispose(); + } + + + + // -------- Graphics2D methods: + + public void draw(Shape shape) + { + state.draw(shape); + } + + public boolean drawImage(Image image, AffineTransform xform, + ImageObserver obs) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public void drawString(String text, int x, int y) + { + state.drawString(text, x, y); + } + + public void drawString(String text, float x, float y) + { + state.drawString(text, x, y); + } + + public void fill(Shape shape) + { + state.fill(shape); + } + + public boolean hit(Rectangle rect, Shape text, boolean onStroke) + { + return state.hit(rect, text, onStroke); + } + + public GraphicsConfiguration getDeviceConfiguration() + { + return config; + } + + public void setPaint(Paint paint) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void setRenderingHint(RenderingHints.Key hintKey, + Object hintValue) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public Object getRenderingHint(RenderingHints.Key hintKey) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public RenderingHints getRenderingHints() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void translate(int x, int y) + { + state.translate(x, y); + } + + public void translate(double tx, double ty) + { + state.translate(tx, ty); + } + + public void rotate(double theta) + { + state.rotate(theta); + } + + public void rotate(double theta, double x, double y) + { + state.rotate(theta, x, y); + } + + public void scale(double scaleX, double scaleY) + { + state.scale(scaleX, scaleY); + } + + public void shear(double shearX, double shearY) + { + state.shear(shearX, shearY); + } + + public void transform(AffineTransform Tx) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void setTransform(AffineTransform Tx) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public AffineTransform getTransform() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public Paint getPaint() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void setBackground(Color color) + { + bg = color; + } + + public Color getBackground() + { + return bg; + } + + public void clip(Shape shape) + { + Shape clip = state.getClip(); + + if ((shape instanceof Rectangle) && (clip instanceof Rectangle)) + { + clip = ((Rectangle) clip).intersection((Rectangle) shape); + state.setClip(clip); + return; + } + + String msg = + "intersecting current clip shape " + clip + " with new shape " + shape + + "has not been implemented yet"; + throw new UnsupportedOperationException(msg); + } +} diff --git a/libjava/gnu/awt/j2d/IntegerGraphicsState.java b/libjava/gnu/awt/j2d/IntegerGraphicsState.java new file mode 100644 index 00000000000..923720e06ae --- /dev/null +++ b/libjava/gnu/awt/j2d/IntegerGraphicsState.java @@ -0,0 +1,409 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.j2d; + +import java.awt.Color; +import java.awt.Image; +import java.awt.Shape; +import java.awt.Rectangle; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.ColorModel; + +/** + * IntegerGraphicsState is one of several graphics state + * implementations. This graphics state is used when the graphics + * object has simple properties, (coordinate translation only, no + * transform) and the backend supports integer coordinates (pixel + * based). For primitive paint operations, this object translates the + * coordinates and forwards the request to the backend. For requests + * to draw arbitrary shapes and paths, this object translates the + * requests to primitive drawing operations supported by the + * backend. IntegerGraphicsState is meant to support the most common + * state of an graphics object. The degree of functionality is roughly + * equivalent with the old java.awt.Graphics API. + */ +public class IntegerGraphicsState extends AbstractGraphicsState +{ + int tx; + int ty; + + DirectRasterGraphics directGfx; + Shape clip; + + public IntegerGraphicsState(DirectRasterGraphics directGfx) + { + this.directGfx = directGfx; + } + + public Object clone() + { + IntegerGraphicsState clone = (IntegerGraphicsState) super.clone(); + clone.directGfx = (DirectRasterGraphics) directGfx.clone(); + + return clone; + } + + public void dispose() + { + DirectRasterGraphics lDeviceGfx = directGfx; + + directGfx = null; + + if (lDeviceGfx != null) + lDeviceGfx.dispose(); + + super.dispose(); + } + + + // -------- Graphics methods: + + public void setColor(Color color) + { + directGfx.setColor(color); + } + + public void setPaintMode() + { + directGfx.setPaintMode(); + } + + public void setXORMode(Color altColor) + { + directGfx.setXORMode(altColor); + } + + public void setFont(Font font) + { + directGfx.setFont(font); + } + + public FontMetrics getFontMetrics(Font font) + { + return directGfx.getFontMetrics(font); + } + + public void setClip(Shape clip) + { + if (clip instanceof Rectangle) + { + Rectangle clipRect = (Rectangle) clip.clone(); + clipRect.x += tx; + clipRect.y += ty; + + this.clip = clipRect; + + directGfx.setClip(clipRect); + return; + } + + String msg = + "translating clip shape " + clip + " into device " + + "coordinate space has not been implemented yet"; + + throw new UnsupportedOperationException(msg); + } + + public Shape getClip() + { + if (clip instanceof Rectangle) + { + Rectangle clipRect = (Rectangle) clip; + clipRect.x -= tx; + clipRect.y -= ty; + return clipRect; + } + + String msg = + "translating clip shape " + clip + " into user " + + "coordinate space has not been implemented yet"; + + throw new UnsupportedOperationException(msg); + } + + public Rectangle getClipBounds() + { + Rectangle clipRect = clip.getBounds(); + + clipRect.x -= tx; + clipRect.y -= ty; + return clipRect; + } + + public void copyArea(int x, int y, + int width, int height, + int dx, int dy) + { + directGfx.copyArea(x+tx, y+ty, width, height, dx, dy); + } + + public void drawLine(int x1, int y1, + int x2, int y2) + { + directGfx.drawLine(x1+tx, y1+ty, x2+tx, y2+ty); + } + + public void fillRect(int x, int y, + int width, int height) + { + directGfx.fillRect(x+tx, y+ty, width, height); + } + + public void clearRect(int x, int y, + int width, int height) + { + directGfx.setColor(frontend.getBackground()); + directGfx.fillRect(x+tx, y+ty, width, height); + directGfx.setColor(frontend.getColor()); + } + + public void drawRoundRect(int x, int y, + int width, int height, + int arcWidth, int arcHeight) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void fillRoundRect(int x, int y, + int width, int height, + int arcWidth, int arcHeight) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void drawOval(int x, int y, + int width, int height) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void fillOval(int x, int y, + int width, int height) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void drawArc(int x, int y, + int width, int height, + int startAngle, int arcAngle) + { + directGfx.drawArc(x+tx, y+ty, width, height, startAngle, arcAngle); + } + + public void fillArc(int x, int y, + int width, int height, + int startAngle, int arcAngle) + { + directGfx.fillArc(x+tx, y+ty, width, height, startAngle, arcAngle); + } + + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) + { + if ((tx == 0) || (ty == 0)) + { + directGfx.drawPolyline(xPoints, yPoints, nPoints); + return; + } + + throw new UnsupportedOperationException("translate not implemented"); + } + + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) + { + if ((tx == 0) || (ty == 0)) + { + directGfx.drawPolygon(xPoints, yPoints, nPoints); + return; + } + + throw new UnsupportedOperationException("translate not implemented"); + } + + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) + { + if ((tx == 0) || (ty == 0)) + { + directGfx.fillPolygon(xPoints, yPoints, nPoints); + return; + } + + throw new UnsupportedOperationException("translate not implemented"); + } + + public boolean drawImage(Image image, int x, int y, + ImageObserver observer) + { + x += tx; + y += ty; + + if (image instanceof BufferedImage) + { + BufferedImage bImage = (BufferedImage) image; + Object config = + bImage.getProperty("java.awt.GraphicsConfiguration"); + + if (config == frontend.config) + return directGfx.drawImage(image, x, y, observer); + + int width = image.getWidth(null); + int height = image.getHeight(null); + + Rectangle bounds = new Rectangle(x, y, width, height); + + MappedRaster mr = directGfx.mapRaster(bounds); + + // manipulate raster here... + ColorModel colorModel = mr.getColorModel(); + WritableRaster raster = mr.getRaster(); + + int xEnd = x + width; + int yEnd = y + height; + + // FIXME: Use the following code only as a fallback. It's SLOW! + + Object rgbElem = null; + for (int yy=0; yy<height; yy++) + { + for (int xx=0; xx<width; xx++) + { + int srgb = bImage.getRGB(xx, yy); + int sa = ((srgb >>> 24) & 0xff) + 1; + int sr = ((srgb >>> 16) & 0xff) + 1; + int sg = ((srgb >>> 8) & 0xff) + 1; + int sb = (srgb & 0xff) + 1; + + rgbElem = raster.getDataElements(xx+x, yy+y, rgbElem); + int drgb = colorModel.getRGB(rgbElem); + int dr = ((drgb >>> 16) & 0xff) + 1; + int dg = ((drgb >>> 8) & 0xff) + 1; + int db = (drgb & 0xff) + 1; + int da = 256 - sa; + + dr = ((sr*sa + dr*da) >>> 8) - 1; + dg = ((sg*sa + dg*da) >>> 8) - 1; + db = ((sb*sa + db*da) >>> 8) - 1; + + drgb = (dr<<16) | (dg<<8) | db; + + rgbElem = colorModel.getDataElements(drgb, rgbElem); + + raster.setDataElements(xx+x, yy+y, rgbElem); + } + } + directGfx.unmapRaster(mr); + return true; + + } + throw new UnsupportedOperationException("drawing image " + image + + "not implemented"); + } + + + // -------- Graphics2D methods: + + public void draw(Shape shape) + { + if (shape instanceof Rectangle) + { + Rectangle rect = (Rectangle) shape; + directGfx.drawRect(rect.x+tx, rect.y+ty, rect.width, rect.height); + return; + } + + throw new UnsupportedOperationException("shape not implemented"); + } + + public void fill(Shape shape) + { + if (shape instanceof Rectangle) + { + Rectangle rect = (Rectangle) shape; + directGfx.fillRect(rect.x+tx, rect.y+ty, rect.width, rect.height); + return; + } + + throw new UnsupportedOperationException("not implemented"); + } + + public boolean hit(Rectangle rect, Shape text, + boolean onStroke) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void drawString(String text, int x, int y) + { + directGfx.drawString(text, x+tx, y+ty); + } + + public void drawString(String text, float x, float y) + { + drawString(text, (int) x, (int) y); + } + + public void translate(int x, int y) + { + tx += x; + ty += y; + } + + public void translate(double tx, double ty) + { + if ((tx == 0) && (ty == 0)) + return; + + needAffineTransform(); + } + + public void rotate(double theta) + { + if (theta == 0) + return; + + needAffineTransform(); + } + + public void rotate(double theta, double x, double y) + { + if (theta == 0) + return; + + needAffineTransform(); + } + + public void scale(double scaleX, double scaleY) + { + if ((scaleX == 1) && (scaleY == 1)) + return; + + needAffineTransform(); + } + + public void shear(double shearX, double shearY) + { + if ((shearX == 0) && (shearY == 0)) + return; + + needAffineTransform(); + } + + private void needAffineTransform() + { + throw new UnsupportedOperationException("state with affine " + + "transform not implemented"); + } +} diff --git a/libjava/gnu/awt/j2d/MappedRaster.java b/libjava/gnu/awt/j2d/MappedRaster.java new file mode 100644 index 00000000000..eb41eecf9ad --- /dev/null +++ b/libjava/gnu/awt/j2d/MappedRaster.java @@ -0,0 +1,72 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.j2d; + +import java.awt.image.WritableRaster; +import java.awt.image.ColorModel; + +/* The raster and associated properties of a mapped screen region. + * The compositing capabilities of backends are often insufficient. + * The backend may not support alpha blending, or may not support some + * other special compositing rule. This means that compositing must + * sometimes be done within the rendering pipeline. The general + * compositing operation consists of combining new color and alpha + * values with existing color values on the drawing surface, to find + * the new color values for the drawing surface. The way the values + * are combined, determines what kind of compositing operation that is + * performed. The default compositing operation is alpha compositing. + * + * <p>In order to perform alpha compositing and other compositing + * operations, we need access to the color values of the imagery that + * has already been drawn on the drawing surface. The + * DirectRasterGraphics interface must therefore contain methods that + * makes it possible to gain access to the pixel values of the drawing + * surface. The methods are modeled after the POSIX mmap() and + * munmap() functions. But, instead of mapping and unmapping portions + * of data from a file descriptor to memory, the methods in + * DirectRasterGraphics maps and unmaps portions of the drawing + * surface to data arrays within writable raster objects. A call to + * mapRaster() will return a writable raster object, encapsulating the + * image data of the drawing surface in the requested domain. The data + * encapsulated by this raster object can be modified using the + * WritableRaster API, or the data buffers can be retrieved from the + * raster, so that the data arrays can be manipulated directly. When + * the raster image has been modified as desired, the data can be + * resynchronized with the drawing surface by calling mapRaster(). + * + * <p>As with mmap() and munmap() the methods may work by direct + * manipulation of shared memory, (i.e. the raster object directly + * wraps the actual image data of the drawing surface), or may make a + * private copy that is resynched when the raster is unmapped. The + * backend may choose to implement either mechanism, and the pipeline + * code should not care what mechanism is actually used. This design + * allows us to make full use of speedups such as X shared memory + * extentions when available. + */ +public class MappedRaster +{ + WritableRaster raster; + ColorModel cm; + + public MappedRaster(WritableRaster raster, ColorModel cm) + { + this.raster = raster; + this.cm = cm; + } + + public final WritableRaster getRaster() + { + return raster; + } + + public final ColorModel getColorModel() + { + return cm; + } +} diff --git a/libjava/gnu/awt/xlib/XCanvasPeer.java b/libjava/gnu/awt/xlib/XCanvasPeer.java new file mode 100644 index 00000000000..5674f5bf2ad --- /dev/null +++ b/libjava/gnu/awt/xlib/XCanvasPeer.java @@ -0,0 +1,388 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.Dimension; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Rectangle; +import java.awt.Color; +import java.awt.Container; +import java.awt.Image; +import java.awt.GraphicsConfiguration; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.AWTEvent; +import java.awt.Cursor; +import java.awt.Shape; + +import java.awt.peer.*; +import java.awt.image.*; + +import java.awt.event.MouseListener; +import java.awt.event.PaintEvent; + +import java.util.EventListener; + +import gnu.gcj.xlib.WMSizeHints; +import gnu.gcj.xlib.Window; +import gnu.gcj.xlib.WindowAttributes; +import gnu.gcj.xlib.Display; +import gnu.gcj.xlib.Visual; +import gnu.gcj.xlib.Screen; +import gnu.gcj.xlib.XImage; + +import gnu.awt.j2d.*; + +public class XCanvasPeer implements CanvasPeer +{ + static final Dimension MIN_SIZE = new Dimension(1, 1); + + public // temporary + + Window window; + Window parent; + + Component component; + XGraphicsConfiguration config; + + public XCanvasPeer(Component component) + { + this.component = component; + + // Set up graphics configuration (ie. screen + visual): + + config = (XGraphicsConfiguration) + component.getGraphicsConfiguration(); + + if (config == null) + { + // This will usually only happen for toplevel windows + config = getXToolkit().getDefaultXGraphicsConfiguration(); + } + + Rectangle bounds = component.getBounds(); + parent = locateParentWindow(bounds); + + // Windows in X must atleast be of size 1x1 + boolean boundsChanged = false; + if (bounds.width < 1) + { + boundsChanged = true; + bounds.width = 1; + } + if (bounds.height < 1) + { + boundsChanged = true; + bounds.height = 1; + } + + /* don't worry about this calling back to us, since the real + component object has not yet received a reference to this peer + object. */ + component.setBounds(bounds); + + WindowAttributes attributes = new WindowAttributes(); + + /* Set background color */ + Color bg = component.getBackground(); + if (bg != null) + { + int[] components = + { + bg.getRed(), + bg.getGreen(), + bg.getBlue(), + 0xff + }; + + ColorModel cm = config.getColorModel(); + long pixel = cm.getDataElement(components, 0); + attributes.setBackground(pixel); + } + + /* Set exposure mask so that we get exposure events + that can be translated into paint() calls. */ + long eventMask = WindowAttributes.MASK_EXPOSURE; + + /* It would be nice to set up all other required events here, but + it is not possible to do so before after all the children of + this component has been realized. The reason is that it is not + determined whether a component is lightweight before after the + addNotify() method has been called. Thus, it is not possible + for parent component to determine what events it needs to + furnish for lightweight children. Instead, we currently rely + on the component calling our setEventMask() method after the + correct event mask has been determined. */ + + attributes.setEventMask(eventMask); + + + // TODO: set more window attributes? + + /* don't allow event queue to process events from the newly + created window before this peer has been registered as client + data. */ + synchronized (getXToolkit().eventLoop) + { + window = new gnu.gcj.xlib.Window(parent, bounds, attributes); + window.setClientData(this); /* make it possible to find back + to this peer object. Used by + XEventQueue. */ + } + + initWindowProperties(); + + if (component.isVisible()) + EventQueue.invokeLater(new DoMap(window)); + } + + /** + * Override this in subclasses to implement other ways of obtaining + * parent windows. Toplevel windows will typically have a different + * implementation. + */ + gnu.gcj.xlib.Window locateParentWindow(Rectangle bounds) + { + Container parent = component.getParent(); + while (parent.isLightweight()) + { + bounds.x += parent.getX(); + bounds.y += parent.getY(); + parent = parent.getParent(); + // a null pointer here is a genuine error + } + + XCanvasPeer parentPeer = (XCanvasPeer) parent.getPeer(); + if (parentPeer == null) + throw new NullPointerException("Parent has no peer. This should " + + "not be possible, since the " + + "calls leading here should come " + + "from parent, after it has " + + "set the parent peer."); + return parentPeer.window; + } + + + /** + * Template method to allow subclasses to apply properties to X11 + * window right after creation. + */ + void initWindowProperties() + { + } + + XToolkit getXToolkit() + { + return XToolkit.INSTANCE; + } + + protected void ensureFlush() + { + getXToolkit().flushIfIdle(); + } + + public Component getComponent() + { + return component; + } + + long getBasicEventMask() + { + return WindowAttributes.MASK_EXPOSURE; + } + + // -------- java.awt.peer.ComponentPeer implementation + + public int checkImage(Image img, int width, int height, ImageObserver o) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + public Image createImage(ImageProducer prod) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + public Image createImage(int width, int height) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + public void dispose() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public GraphicsConfiguration getGraphicsConfiguration() + { + return config; + } + + public FontMetrics getFontMetrics(Font f) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public Graphics getGraphics() + { + DirectRasterGraphics gfxDevice = new XGraphics(window, config); + IntegerGraphicsState igState = new IntegerGraphicsState(gfxDevice); + Graphics2DImpl gfx2d = new Graphics2DImpl(config); + + gfx2d.setState(igState); + gfx2d.setColor(component.getBackground()); + return gfx2d; + } + + public Point getLocationOnScreen() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public Dimension getMinimumSize () + { + return MIN_SIZE; + } + + public Dimension getPreferredSize () + { + return component.getSize(); + } + + public Toolkit getToolkit() + { + return getXToolkit(); + } + + public void handleEvent(AWTEvent event) + { + } + + public boolean isFocusTraversable() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void paint(Graphics gfx) + { + // do nothing by default + } + + public boolean prepareImage(Image img, int width, int height, + ImageObserver o) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void print(Graphics graphics) + { + paint(graphics); + } + + public void repaint(long tm, int x, int y, int w, int h) + { + /* TODO? + + X allows intelligent X servers to do smart + refreshing. Perhaps involve X in repainting of components, + rather that keeping it all within the local event queue. */ + + PaintEvent updateEvent = new PaintEvent(component, + PaintEvent.UPDATE, + new Rectangle(x, y, w, h)); + getXToolkit().queue.postEvent(updateEvent); + } + + public void requestFocus() + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void setBackground(Color color) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void setBounds(int x, int y, int width, int height) + { + width = Math.max(width, 1); + height = Math.max(height, 1); + window.setBounds(x, y, width, height); + ensureFlush(); + } + + public void setCursor(Cursor cursor) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void setEnabled(boolean enabled) + { + throw new UnsupportedOperationException("FIXME, not implemented"); + } + + public void setEventMask(long eventMask) + { + WindowAttributes attributes = new WindowAttributes(); + + long xEventMask = getBasicEventMask(); + + if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) + { + xEventMask |= + WindowAttributes.MASK_BUTTON_PRESS | + WindowAttributes.MASK_BUTTON_RELEASE; + } + + attributes.setEventMask(xEventMask); + window.setAttributes(attributes); + ensureFlush(); + } + + public void setFont(Font font) + { + /* default canvas peer does keep track of font, since it won't + write anything. */ + } + + public void setForeground(Color color) + { + /* default canvas peer does keep track of foreground, since it won't + paint anything. */ + } + + public void setVisible(boolean visible) + { + if (visible) + { + window.map(); + ensureFlush(); + } + else + { + throw new UnsupportedOperationException("unmap not implemented"); + } + } + + static class DoMap implements Runnable + { + Window window; + public DoMap(Window w) + { + this.window = w; + } + + public void run() + { + window.map(); + } + } +} + diff --git a/libjava/gnu/awt/xlib/XEventLoop.java b/libjava/gnu/awt/xlib/XEventLoop.java new file mode 100644 index 00000000000..4d293208939 --- /dev/null +++ b/libjava/gnu/awt/xlib/XEventLoop.java @@ -0,0 +1,268 @@ +package gnu.awt.xlib; + +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +import java.awt.*; + +import gnu.awt.LightweightRedirector; +import gnu.gcj.xlib.Display; +import gnu.gcj.xlib.XAnyEvent; +import gnu.gcj.xlib.XExposeEvent; +import gnu.gcj.xlib.XButtonEvent; +import gnu.gcj.xlib.XConfigureEvent; +import java.awt.event.PaintEvent; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.util.Vector; + +public class XEventLoop implements Runnable +{ + Display display; + EventQueue queue; + XAnyEvent anyEvent; + Thread eventLoopThread; + + LightweightRedirector lightweightRedirector = new LightweightRedirector(); + + public XEventLoop(Display display, EventQueue queue) + { + this.display = display; + this.queue = queue; + + anyEvent = new XAnyEvent(display); + eventLoopThread = new Thread(this, "AWT thread for XEventLoop"); + eventLoopThread.start(); + } + + public void run() + { + while (true) + postNextEvent(); + } + + void postNextEvent() + { + try + { + AWTEvent evt = getNextEvent(); + queue.postEvent(evt); + + } + catch (InterruptedException ie) + { + // FIXME: what now? + System.err.println(ie); + } + } + + /** get next event. Will block until events become available. */ + + public AWTEvent getNextEvent() + { + // ASSERT: + if (isIdle()) + throw new Error("should not be idle"); + + AWTEvent event = null; + while (event == null) + { + loadNextEvent(); + event = createEvent(); + } + + event = lightweightRedirector.redirect(event); + + return event; + } + + void loadNextEvent() + { + try + { + setIdle(true); + + /* The code below will result in an XFlush(). However, + while we are waiting for events after calling XFlush(), + new X requests issued on other threads will not + automatically be flushed. This can lead to a deadlock + since XFlush() will not be called before after the + processing of the next event, and new events arriving + might be dependent on the delivery of the X + requests. + + Code that issues X requests should therefore call + flushIfIdle() after they're done, to ensure that the + requests are delivered in a timely manner. XFlush is not + run if event processing is underway, since we are assured + that the event loop execution will return to this point, + where requests are flushed again, before waiting for new + events. + + Alternatively, do the work on the AWT thread, since the + XEventQueue knows how to flush the display when it runs out + of events. */ + + //display.flush(); // implicit? + anyEvent.loadNext(); + } + catch (RuntimeException re) + { + System.err.println("Exception thrown on event thread:" + re); + } + finally + { + setIdle(false); + } + } + + /** + * @returns an AWT event created based on the current XEvent. + * Returns null if the current XEvent does not map to any perticular + * AWT event. + */ + + AWTEvent createEvent() + { + /* avoid attempting to get client data before client data has + been set. */ + Object peer; + synchronized (this) + { + peer = anyEvent.getWindow().getClientData(); + } + + Component source = null; + + // Try to identify source component + + if (peer instanceof XCanvasPeer) + { + source = ((XCanvasPeer) peer).getComponent(); + } + + if (source == null) + { + String msg = "unable to locate source for event (" + + anyEvent + ")"; + throw new RuntimeException(msg); + } + + /* if a mapping from anyEvent to AWTEvent is possible, construct a + new AWTEvent and return it. */ + + int type = anyEvent.getType(); + switch (type) + { + case XAnyEvent.TYPE_EXPOSE: + return createPaintEvent(source); + case XAnyEvent.TYPE_BUTTON_PRESS: + case XAnyEvent.TYPE_BUTTON_RELEASE: + return createMouseEvent(type, source); + case XAnyEvent.TYPE_UNMAP_NOTIFY: + case XAnyEvent.TYPE_MAP_NOTIFY: + case XAnyEvent.TYPE_REPARENT_NOTIFY: + return null; // ignore for now + case XAnyEvent.TYPE_CONFIGURE_NOTIFY: + configureNotify(peer); + return null; + + default: + String msg = "Do no know how to handle event (" + anyEvent + ")"; + throw new RuntimeException(msg); + } + } + + AWTEvent createPaintEvent(Component src) + { + XExposeEvent expose = new XExposeEvent(anyEvent); + PaintEvent pe = new PaintEvent(src, PaintEvent.PAINT, + expose.getBounds()); + return pe; + } + + AWTEvent createMouseEvent(int type, Component src) + { + XButtonEvent buttonEvt = new XButtonEvent(anyEvent); + + int modifiers = 0; //buttonToModifierMap[buttonEvt.button]; + + /* Warning: this makes assumptions on the contents of + X.h... Button1 = 1, Button2 = 2, etc... */ + switch (buttonEvt.button) + { + case 1: + modifiers = InputEvent.BUTTON1_MASK; + break; + case 2: + modifiers = InputEvent.BUTTON2_MASK; + break; + case 3: + modifiers = InputEvent.BUTTON2_MASK; + break; + } + + int state = buttonEvt.state; + + // remap bits from state to modifiers: + + if ((state & XButtonEvent.MASK_SHIFT) != 0) + modifiers |= InputEvent.SHIFT_MASK; + + + if ((state & XButtonEvent.MASK_CONTROL) != 0) + modifiers |= InputEvent.CTRL_MASK; + + + /* FIXME: we need additional X code to properly map MODn states to + input modifiers */ + + int clickCount = 1; // FIXME... Can't get this from X. + boolean popupTrigger = false; // FIXME: look up policy somewhere + + int x = buttonEvt.x; + int y = buttonEvt.y; + + int id = (type == XAnyEvent.TYPE_BUTTON_PRESS) ? + MouseEvent.MOUSE_PRESSED : + MouseEvent.MOUSE_RELEASED; + + MouseEvent me = new MouseEvent(src, + id, + buttonEvt.time, modifiers, + buttonEvt.x, buttonEvt.y, + clickCount, popupTrigger); + return me; + } + + void configureNotify(Object peerObj) + { + XConfigureEvent configEvent = new XConfigureEvent(anyEvent); + XFramePeer peer = (XFramePeer) peerObj; + + peer.configureNotify(configEvent); + } + + public void flushIfIdle() + { + if (isIdle()) + display.flush(); + } + + volatile boolean idle = false; + + final synchronized void setIdle(boolean idle) + { + this.idle = idle; + } + + final synchronized boolean isIdle() + { + return idle; + } +} diff --git a/libjava/gnu/awt/xlib/XEventQueue.java b/libjava/gnu/awt/xlib/XEventQueue.java new file mode 100644 index 00000000000..ea2ad186060 --- /dev/null +++ b/libjava/gnu/awt/xlib/XEventQueue.java @@ -0,0 +1,34 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.*; + +import gnu.gcj.xlib.Display; + +/** + * The only difference here from a standard EventQueue is that the X + * display connection is flushed before waiting for more events. + */ +public class XEventQueue extends EventQueue +{ + Display display; + + public XEventQueue(Display display) + { + this.display = display; + } + + public AWTEvent getNextEvent() throws InterruptedException + { + if ((peekEvent() == null) && (display != null)) + display.flush(); + return super.getNextEvent(); + } +} diff --git a/libjava/gnu/awt/xlib/XFontMetrics.java b/libjava/gnu/awt/xlib/XFontMetrics.java new file mode 100644 index 00000000000..4e45a1f8250 --- /dev/null +++ b/libjava/gnu/awt/xlib/XFontMetrics.java @@ -0,0 +1,47 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.FontMetrics; + +public class XFontMetrics extends FontMetrics +{ + gnu.gcj.xlib.Font xfont; + + public XFontMetrics(gnu.gcj.xlib.Font xfont, java.awt.Font awtFont) + { + super(awtFont); + this.xfont = xfont; + } + + public int getAscent() + { + return xfont.getAscent(); + } + + public int getDescent() + { + return xfont.getDescent(); + } + + public int getMaxAscent() + { + return xfont.getMaxAscent(); + } + + public int getMaxDescent() + { + return xfont.getMaxDescent(); + } + + public int stringWidth(String str) + { + return xfont.getStringWidth(str); + } +} diff --git a/libjava/gnu/awt/xlib/XFramePeer.java b/libjava/gnu/awt/xlib/XFramePeer.java new file mode 100644 index 00000000000..0f55088d023 --- /dev/null +++ b/libjava/gnu/awt/xlib/XFramePeer.java @@ -0,0 +1,174 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.*; +import java.awt.peer.*; +import java.awt.image.*; +import gnu.gcj.xlib.WMSizeHints; +import gnu.gcj.xlib.WindowAttributes; +import gnu.gcj.xlib.Display; +import gnu.gcj.xlib.Visual; +import gnu.gcj.xlib.Screen; +import gnu.gcj.xlib.XConfigureEvent; + +/** FIXME: a lot of the code here should be moved down to XWindowPeer. */ + +public class XFramePeer extends XCanvasPeer implements FramePeer +{ + + public XFramePeer(Frame frame) + { + super(frame); + + // Set some defaults for a toplevel component: + if (frame.getFont() == null) + frame.setFont(new Font("helvetica", Font.PLAIN, 12)); + + if (frame.getBackground() == null) + frame.setBackground(Color.lightGray); + + if (frame.getForeground() == null) + frame.setForeground(Color.black); + } + + /** Find parent window for toplevel window, ie. root window of + selected screen. Bounds are not changed. */ + gnu.gcj.xlib.Window locateParentWindow(Rectangle bounds) + { + Screen screen = config.getVisual().getScreen(); + return screen.getRootWindow(); + } + + void initWindowProperties() + { + Frame frame = (Frame) component; + setResizable(frame.isResizable()); + String title = frame.getTitle(); + if (!title.equals("")) setTitle(title); + } + + long getBasicEventMask() + { + return super.getBasicEventMask() | + WindowAttributes.MASK_STRUCTURE_NOTIFY; + } + + void configureNotify(XConfigureEvent configEvent) + { + component.setBounds(configEvent.getBounds()); + + /* FIXME: Validation should probably not be done here. The best + strategy is probably to validate on the AWT thread in response + to an ComponentEvent. This will make it possible to coalesce + resize validations. */ + component.validate(); + } + + /* Overridden to ignore request to set bounds if the request occurs + on the X event loop thread. It is assumed that all requests that + occur on the X event loop thread are results of XConfigureNotify + events, in which case the X window already has the desired + bounds. */ + public void setBounds(int x, int y, int width, int height) + { + if (Thread.currentThread() == getXToolkit().eventLoop.eventLoopThread) + return; + + super.setBounds(x, y, width, height); + } + + // Implementing ContainerPeer: + + static final Insets INSETS_0_PROTOTYPE = new Insets(0, 0, 0, 0); + + public Insets getInsets() + { + return (Insets) INSETS_0_PROTOTYPE.clone(); + } + + public void beginValidate() + { + } + + public void endValidate() + { + // reassert sizing hints + Frame frame = (Frame) component; + setResizable(frame.isResizable()); + } + + + // Implementing WindowPeer: + + public void toBack() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void toFront() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + // Implementing FramePeer: + + public void setIconImage(Image image) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void setMenuBar(MenuBar mb) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public void setTitle(String title) + { + synchronized (window.getDisplay()) + { + // Oh, what a nice implementation :-) + window.setProperty("WM_NAME", "STRING", title); + + ensureFlush(); + } + } + + public void setResizable(boolean resizable) + { + Frame frame = (Frame) component; + + WMSizeHints sizeHints = new WMSizeHints(); + if (resizable) + { + Dimension minSize = frame.getMinimumSize(); + sizeHints.setMinSize(minSize.width, minSize.height); + + Dimension maxSize = frame.getMaximumSize(); + + if ((maxSize.width < Short.MAX_VALUE) || + (maxSize.height < Short.MAX_VALUE)) + { + maxSize.width = Math.min(maxSize.width, Short.MAX_VALUE); + maxSize.height = Math.min(maxSize.height, Short.MAX_VALUE); + sizeHints.setMaxSize(maxSize.width, maxSize.height); + } + } + else + { + // lock resizing to current bounds + Dimension size = frame.getSize(); + sizeHints.setMinSize(size.width, size.height); + sizeHints.setMaxSize(size.width, size.height); + } + sizeHints.applyNormalHints(window); + } +} diff --git a/libjava/gnu/awt/xlib/XGraphics.java b/libjava/gnu/awt/xlib/XGraphics.java new file mode 100644 index 00000000000..27b07a2369a --- /dev/null +++ b/libjava/gnu/awt/xlib/XGraphics.java @@ -0,0 +1,279 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.*; +import java.awt.image.WritableRaster; +import java.awt.image.Raster; +import java.awt.image.DataBuffer; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.BufferedImage; +import gnu.gcj.xlib.GC; +import gnu.gcj.xlib.XImage; +import gnu.gcj.xlib.Drawable; +import gnu.gcj.xlib.Window; +import gnu.gcj.xlib.Drawable; +import gnu.gcj.xlib.Visual; +import gnu.awt.j2d.DirectRasterGraphics; +import gnu.awt.j2d.MappedRaster; + +public class XGraphics implements Cloneable, DirectRasterGraphics +{ + static class XRaster extends MappedRaster + { + XImage ximage; + + public XRaster(WritableRaster raster, XImage ximage, ColorModel cm) + { + super(raster, cm); + this.ximage = ximage; + } + } + + GC context; + XGraphicsConfiguration config; + Rectangle clipBounds; + + XFontMetrics metrics; + + + public Object clone() + { + XGraphics gfxCopy = (XGraphics) super.clone(); + gfxCopy.context = context.create(); + + return gfxCopy; + } + + public void dispose() + { + GC lContext = context; + context = null; + config = null; + clipBounds = null; + + if (lContext != null) + { + lContext.dispose(); + } + } + + public XGraphics(Drawable drawable, XGraphicsConfiguration config) + { + context = new GC(drawable); + this.config = config; + } + + public void setColor(Color color) + { + context.setForeground(config.getPixel(color)); + } + + public void setPaintMode() + { + throw new UnsupportedOperationException("not implemented"); + } + + public void setXORMode(Color c1) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void setFont(Font font) + { + if ((metrics != null) && font.equals(metrics.getFont())) return; + + metrics = config.getXFontMetrics(font); + context.setFont(metrics.xfont); + } + + public FontMetrics getFontMetrics(Font font) + { + if ((metrics != null) && font.equals(metrics.getFont())) + return metrics; + + return config.getXFontMetrics(font); + } + + public void setClip(int x, int y, int width, int height) + { + Rectangle[] rects = { new Rectangle(x, y, width, height) }; + context.setClipRectangles(rects); + } + + public void setClip(Shape clip) + { + /* TODO: create a special RectangleUnion shape that can be + used to draw advantage of the GCs ability to set multiple + rectangles. + */ + + /* FIXME: creating all these objects is wasteful and can be + costly in the long run, since this code is run at every + expose. */ + Rectangle newClipBounds = clip.getBounds(); + + if ((clipBounds != null) && !clipBounds.contains(newClipBounds)) + { + System.err.println("warning: old clip ("+ clipBounds +") does " + + "not fully contain new clip (" + + newClipBounds + ")"); + } + clipBounds = newClipBounds; + Rectangle[] rects = { clipBounds }; + context.setClipRectangles(rects); + } + + public void copyArea(int x, int y, int width, int height, int + dx, int dy) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void drawLine(int x1, int y1, int x2, int y2) + { + context.drawLine(x1, y1, x2, y2); + } + + public void drawRect(int x, int y, int width, int height) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public void fillRect(int x, int y, int width, int height) + { + context.fillRectangle(x, y, width, height); + } + + public void drawArc(int x, int y, int width, int height, int + startAngle, int arcAngle) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void fillArc(int x, int y, int width, int height, int + startAngle, int arcAngle) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void drawPolyline(int[] xPoints, int[] yPoints, int + nPoints) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void drawPolygon(int[] xPoints, int[] yPoints, int + nPoints) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void fillPolygon(int[] xPoints, int[] yPoints, int + nPoints) + { + throw new UnsupportedOperationException("not implemented"); + } + + public void drawString(String str, int x, int y) + { + context.drawString(str, x, y); + } + + public boolean drawImage(Image img, int x, int y, + ImageObserver observer) + { + if (clipBounds == null) + return false; // ***FIXME*** + + if (!(img instanceof BufferedImage)) + { + throw new AWTError("unknown image class"); + } + + BufferedImage bimg = (BufferedImage) img; + + XImage ximg = (XImage) bimg.getProperty("gnu.gcj.xlib.XImage"); + if (ximg == null) + { + System.err.println("FIXME: skipping null XImage, should " + + "really do on the spot conversion"); + return false; + } + + /* + +------------------ + | clip + | +---------+ + | img | | + | +--+-------+ | + | | | | | + | | | | | + | | +-------+-+ + | | | + | +----------+ + */ + + int iLeft = Math.max(x, clipBounds.x); + int iTop = Math.max(y, clipBounds.y); + int iRight = Math.min(x + bimg.getWidth(), + clipBounds.x + clipBounds.width); + int iBottom = Math.min(y + bimg.getHeight(), + clipBounds.y + clipBounds.height); + + int srcX = iLeft - x; + int srcY = iTop - y; + + int width = iRight - iLeft; + int height = iBottom - iTop; + + if ((width > 0) && (height > 0)) + context.putImage(ximg, srcX, srcY, iLeft, iTop, width, height); + + return true; + } + + public MappedRaster mapRaster(Rectangle bounds) + { + Visual visual = config.getVisual(); + XImage ximage = new XImage(visual, bounds.width, bounds.height, + false // do not auto allocate memory + ); + + WritableRaster raster = + config.createRasterForXImage(ximage, + new Point(bounds.x, bounds.y)); + + DataBuffer dataB = raster.getDataBuffer(); + XGraphicsConfiguration.attachData(ximage, dataB, 0); + + Drawable drawable = context.getDrawable(); + + // TODO: restrict to clipping + + Rectangle mBounds = drawable.copyIntoXImage(ximage, bounds, 0, 0); + + return new XRaster(raster, ximage, config.imageCM); + } + + + public void unmapRaster(MappedRaster mappedRaster) + { + XRaster xraster = (XRaster) mappedRaster; + XImage ximage = xraster.ximage; + Raster raster = xraster.getRaster(); + int x = raster.getMinX(); + int y = raster.getMinY(); + int width = raster.getWidth(); + int height = raster.getHeight(); + + context.putImage(ximage, 0, 0, x, y, width, height); + } +} diff --git a/libjava/gnu/awt/xlib/XGraphicsConfiguration.java b/libjava/gnu/awt/xlib/XGraphicsConfiguration.java new file mode 100644 index 00000000000..af2663ba58b --- /dev/null +++ b/libjava/gnu/awt/xlib/XGraphicsConfiguration.java @@ -0,0 +1,367 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.GraphicsConfiguration; +import java.awt.Rectangle; +import java.awt.Graphics2D; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Color; +import java.awt.color.ColorSpace; +import java.awt.image.*; +import java.awt.geom.AffineTransform; +import gnu.gcj.xlib.GC; +import gnu.gcj.xlib.Drawable; +import gnu.gcj.xlib.Window; +import gnu.gcj.xlib.XImage; +import gnu.gcj.xlib.Visual; +import gnu.gcj.xlib.Colormap; +import gnu.gcj.xlib.XColor; +import gnu.gcj.xlib.Screen; +import gnu.gcj.xlib.Display; +import gnu.gcj.awt.Buffers; +import java.util.Hashtable; + +public class XGraphicsConfiguration extends GraphicsConfiguration +{ + //public abstract GraphicsDevice getDevice(); + + Visual visual; + int format; + Colormap colormap; + ColorModel imageCM; + ColorModel pixelCM; + + public XGraphicsConfiguration(Visual visual) + { + this.visual = visual; + } + + public BufferedImage createCompatibleImage(int width, int height) + { + XImage ximg = new XImage(visual, width, height, + false // do not auto allocate memory + ); + + Point origin = new Point(0, 0); + WritableRaster raster = createRasterForXImage(ximg, origin); + + /* This is not a good way of doing this. Multiple toolkits may + want to share the BufferedImage. */ + Hashtable props = new Hashtable(); + props.put("gnu.gcj.xlib.XImage", ximg); + props.put("java.awt.GraphicsConfiguration", this); + + BufferedImage bimg = new BufferedImage(imageCM,raster, false, props); + + DataBuffer dataB = raster.getDataBuffer(); + attachData(ximg, dataB, 0); + return bimg; + } + + WritableRaster createRasterForXImage(XImage ximage, Point origin) + { + if (imageCM == null) prepareColorModel(ximage); + + /* + This will not work, since it creates a sample model that + does not necessarily match the format of the XImage. + + WritableRaster raster = + imageCM.createCompatibleWritableRaster(width, height); */ + + // Create a sample model matching the XImage: + + SampleModel imageSM = null; + + int width = ximage.getWidth(); + int height = ximage.getHeight(); + int bitsPerPixel = ximage.getBitsPerPixel(); + int dataType = + Buffers.smallestAppropriateTransferType(bitsPerPixel); + int bitsPerDataElement = DataBuffer.getDataTypeSize(dataType); + int scanlineStride = ximage.getBytesPerLine()*8/bitsPerDataElement; + + if (imageCM instanceof IndexColorModel) + { + int[] bandOffsets = {0}; + imageSM = new ComponentSampleModel(dataType, + width, height, + 1, // pixel stride + scanlineStride, + bandOffsets); + } + else if (imageCM instanceof PackedColorModel) + { + PackedColorModel pcm = (PackedColorModel) imageCM; + int[] masks = pcm.getMasks(); + + imageSM = new SinglePixelPackedSampleModel(dataType, + width, height, + scanlineStride, + masks); + } + + if (imageSM == null) + { + throw new UnsupportedOperationException("creating sample model " + + "for " + imageCM + + " not implemented"); + } + + WritableRaster raster = Raster.createWritableRaster(imageSM, origin); + return raster; + } + + + + /** + * Attach a the memory of a data buffer to an XImage + * structure. [This method is not gnu.awt.xlib specific, and should + * maybe be moved to a different location.] + * + * @param offset Offset to data. The given offset does not include + * data buffer offset, which will also be added. */ + static void attachData(XImage ximage, DataBuffer dataB, int offset) + { + offset += dataB.getOffset(); + switch (dataB.getDataType()) + { + case DataBuffer.TYPE_BYTE: + ximage.setData(((DataBufferByte) dataB).getData(), offset); + break; + case DataBuffer.TYPE_USHORT: + ximage.setData(((DataBufferUShort) dataB).getData(), offset); + break; + case DataBuffer.TYPE_INT: + ximage.setData(((DataBufferInt) dataB).getData(), offset); + break; + default: + throw + new UnsupportedOperationException("Do not know how to " + + "set data for data " + + "type " + + dataB.getDataType()); + } + } + + void prepareColorModel(XImage ximage) + { + format = ximage.getFormat(); + int bitsPerPixel = ximage.getBitsPerPixel(); + switch (format) { + case XImage.ZPIXMAP_FORMAT: + calcZPixmapModels(bitsPerPixel); + break; + + default: + throw new UnsupportedOperationException("unimplemented format"); + } + } + + void calcZPixmapModels(int bitsPerPixel) + { + switch (visual.getVisualClass()) + { + case Visual.VC_TRUE_COLOR: + calcDecomposedRGBModels(bitsPerPixel); + break; + case Visual.VC_PSEUDO_COLOR: + calcPseudoColorModels(bitsPerPixel); + break; + default: + String msg = "unimplemented visual class"; + throw new UnsupportedOperationException(msg); + } + } + + void calcDecomposedRGBModels(int bitsPerPixel) + { + int dataType = Buffers.smallestAppropriateTransferType(bitsPerPixel); + + + if (DataBuffer.getDataTypeSize(dataType) == bitsPerPixel) + { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); + + imageCM = new DirectColorModel(cs, + visual.getDepth(), + visual.getRedMask(), + visual.getGreenMask(), + visual.getBlueMask(), + 0, // no alpha + false, + dataType); + } + else + { + throw new + UnsupportedOperationException("unimplemented bits per pixel"); + } + } + + void calcPseudoColorModels(int bitsPerPixel) + { + if (colormap == null) + colormap = visual.getScreen().getDefaultColormap(); + + XColor[] colArray = colormap.getXColors(); + + int numCol = colArray.length; + byte[] rmap = new byte[numCol]; + byte[] gmap = new byte[numCol]; + byte[] bmap = new byte[numCol]; + byte[] amap = new byte[numCol]; + + for (int i=0; i < numCol; i++) + { + XColor color = colArray[i]; + if (color.getFlags() == Colormap.FLAG_SHARED) + { + rmap[i] = (byte) (color.getRed() >> 8); + gmap[i] = (byte) (color.getGreen() >> 8); + bmap[i] = (byte) (color.getBlue() >> 8); + amap[i] = (byte) 0xff; + } // else, leave default zero values... + } + + imageCM = new IndexColorModel(visual.getDepth(), numCol, + rmap, gmap, bmap, amap); + } + + public BufferedImage createCompatibleImage(int width, + int height, + int transparency) + { + throw new UnsupportedOperationException("not implemented"); + } + + /** + * FIXME: I'm not sure which color model that should be returned here. + */ + public ColorModel getColorModel() + { + if (pixelCM == null) + preparePixelCM(); + return pixelCM; + } + + void preparePixelCM() + { + switch (visual.getVisualClass()) + { + case Visual.VC_TRUE_COLOR: + pixelCM = new DirectColorModel(visual.getDepth(), + visual.getRedMask(), + visual.getGreenMask(), + visual.getBlueMask()); + break; + case Visual.VC_PSEUDO_COLOR: + + if (colormap == null) + colormap = visual.getScreen().getDefaultColormap(); + + XColor[] colArray = colormap.getXColors(); + + int numCol = colArray.length; + byte[] rmap = new byte[numCol]; + byte[] gmap = new byte[numCol]; + byte[] bmap = new byte[numCol]; + byte[] amap = new byte[numCol]; + + for (int i=0; i < numCol; i++) + { + XColor color = colArray[i]; + if (color.getFlags() == Colormap.FLAG_SHARED) { + rmap[i] = (byte) (color.getRed() >> 8); + gmap[i] = (byte) (color.getGreen() >> 8); + bmap[i] = (byte) (color.getBlue() >> 8); + amap[i] = (byte) 0xff; + } // else, leave default zero values... + + } + + pixelCM = new IndexColorModel(visual.getDepth(), numCol, + rmap, gmap, bmap, amap); + break; + default: + throw new UnsupportedOperationException("not implemented"); + } + } + + public ColorModel getColorModel(int transparency) + { + throw new UnsupportedOperationException("not implemented"); + } + + public AffineTransform getDefaultTransform() + { + throw new UnsupportedOperationException("not implemented"); + } + + public AffineTransform getNormalizingTransform() + { + throw new UnsupportedOperationException("not implemented"); + } + + public Rectangle getBounds() + { + throw new UnsupportedOperationException("not implemented"); + } + + Visual getVisual() + { + return visual; + } + + /* FIXME: This should be moved to XGraphicsDevice... */ + XFontMetrics getXFontMetrics(java.awt.Font awtFont) + { + // FIXME: do caching... + + String family = "*"; + String name = awtFont.getName(); + String weight = awtFont.isBold() ? "bold" : "medium"; + String slant = awtFont.isItalic() ? "i" : "r"; + String addStyle = "*"; + String pixelSize = "*"; + String pointSize = awtFont.getSize() + "0"; + String xres = "*"; + String yres = "*"; + String spacing = "*"; + String averageWidth = "*"; + String charset = "*"; + + String logicalFontDescription = + family + "-" + name + "-" + weight + "-" + + slant + "-" + addStyle + "-" + pixelSize + "-" + + pointSize + "-" + xres + "-" + yres + "-" + + spacing + "-" + averageWidth + "-" + charset; + + Display display = visual.getScreen().getDisplay(); + gnu.gcj.xlib.Font xfont = + new gnu.gcj.xlib.Font(display, logicalFontDescription); + return new XFontMetrics(xfont, awtFont); + } + + int getPixel(Color color) + { + int[] components = + { + color.getRed(), + color.getGreen(), + color.getBlue(), + 0xff + }; + + ColorModel cm = getColorModel(); + return cm.getDataElement(components, 0); + } +} diff --git a/libjava/gnu/awt/xlib/XPanelPeer.java b/libjava/gnu/awt/xlib/XPanelPeer.java new file mode 100644 index 00000000000..c4ff3f17b71 --- /dev/null +++ b/libjava/gnu/awt/xlib/XPanelPeer.java @@ -0,0 +1,52 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.*; +import java.awt.peer.*; +import java.awt.image.*; +import gnu.gcj.xlib.WMSizeHints; +import gnu.gcj.xlib.WindowAttributes; +import gnu.gcj.xlib.Display; +import gnu.gcj.xlib.Visual; +import gnu.gcj.xlib.Screen; + +public class XPanelPeer extends XCanvasPeer implements PanelPeer +{ + + public XPanelPeer(Panel panel) + { + super(panel); + } + + // no reason to override yet + //void initWindowProperties(); + //gnu.gcj.xlib.Window getParentWindow(); + + + // Implementing ContainerPeer: + + // Default is no insets... + static final Insets INSETS_0_PROTOTYPE = new Insets(0, 0, 0, 0); + + public Insets getInsets() + { + return (Insets) INSETS_0_PROTOTYPE.clone(); + } + + public void beginValidate() + { + // NOP + } + + public void endValidate() + { + // NOP + } +} diff --git a/libjava/gnu/awt/xlib/XToolkit.java b/libjava/gnu/awt/xlib/XToolkit.java new file mode 100644 index 00000000000..e400b05e648 --- /dev/null +++ b/libjava/gnu/awt/xlib/XToolkit.java @@ -0,0 +1,333 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt.xlib; + +import java.awt.*; +import java.awt.peer.*; +import java.awt.image.ImageProducer; +import java.awt.image.ImageObserver; +import java.net.*; +import java.awt.datatransfer.Clipboard; + +import gnu.gcj.xlib.Display; +import gnu.gcj.xlib.Screen; +import gnu.gcj.xlib.Visual; + +public class XToolkit extends Toolkit +{ + static XToolkit INSTANCE; + + Display display; + + EventQueue queue; + XEventLoop eventLoop; + + XGraphicsConfiguration defaultConfig; + + public XToolkit() + { + INSTANCE = this; + display = new Display(); + synchronized (display) + { + queue = new XEventQueue(display); + eventLoop = new XEventLoop(display, queue); + } + } + + public void flushIfIdle() + { + eventLoop.flushIfIdle(); + } + + protected ButtonPeer createButton(Button frontend) + { + // FIXME: Stubbed out, needs Swing: + /* + XCanvasPeer realPeer = new XCanvasPeer(frontend); + SButtonPeer sbPeer = new SButtonPeer(frontend, realPeer); + return sbPeer; + */ + return null; + } + + protected TextFieldPeer createTextField(TextField frontend) + { + return null; // FIXME + } + + protected LabelPeer createLabel(Label frontend) + { + return null; // FIXME + } + + protected ListPeer createList(List frontend) + { + return null; // FIXME + } + + protected CheckboxPeer createCheckbox(Checkbox frontend) + { + return null; // FIXME + } + + protected ScrollbarPeer createScrollbar(Scrollbar frontend) + { + return null; // FIXME + } + + protected ScrollPanePeer createScrollPane(ScrollPane frontend) + { + return null; // FIXME + } + + protected TextAreaPeer createTextArea(TextArea frontend) + { + return null; // FIXME + } + + protected ChoicePeer createChoice(Choice frontend) + { + return null; // FIXME + } + + protected FramePeer createFrame(Frame frontend) { + return new XFramePeer(frontend); + } + + protected CanvasPeer createCanvas(Canvas frontend) { + XCanvasPeer peer = new XCanvasPeer(frontend); + return peer; + } + + protected PanelPeer createPanel(Panel frontend) { + return new XPanelPeer(frontend); + } + + protected WindowPeer createWindow(Window frontend) + { + return null; // FIXME + } + + protected DialogPeer createDialog(Dialog frontend) + { + return null; // FIXME + } + + protected MenuBarPeer createMenuBar(MenuBar frontend) + { + return null; // FIXME + } + + protected MenuPeer createMenu(Menu frontend) + { + return null; // FIXME + } + + protected PopupMenuPeer createPopupMenu(PopupMenu frontend) + { + return null; // FIXME + } + + protected MenuItemPeer createMenuItem(MenuItem frontend) + { + return null; // FIXME + } + + protected FileDialogPeer createFileDialog(FileDialog frontend) + { + return null; // FIXME + } + + protected CheckboxMenuItemPeer + createCheckboxMenuItem(CheckboxMenuItem frontend) + { + return null; // FIXME + } + + protected java.awt.peer.FontPeer getFontPeer(String name, int style) + { + return null; + } + + public Dimension getScreenSize() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public int getScreenResolution() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public java.awt.image.ColorModel getColorModel() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public String[] getFontList() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public FontMetrics getFontMetrics(Font font) + { + return defaultConfig.getXFontMetrics(font); + } + + public void sync() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public Image getImage(String filename) + { + return createImage(filename); + } + + public Image getImage(URL url) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public Image createImage(String filename) + { + // FIXME: Stubbed out. We need a proper image I/O API. + + /* + BufferedImage jpeg; + FileInputStream fis = openFile(filename); + if (fis == null) + return null; + + BasicRasterImageConsumer consumer = new BasicRasterImageConsumer(); + JPEGImageDecoder jid = new JPEGImageDecoder(fis); + + jid.startProduction(consumer); + jpeg = consumer.getImage(); + + int w = jpeg.getWidth(); + int h = jpeg.getHeight(); + + BufferedImage img = + getDefaultXGraphicsConfiguration().createCompatibleImage(w, h); + + Renderers renderers = Renderers.getInstance(); + + RasterOp renderer = renderers.createRenderer(jpeg.getColorModel(), + jpeg.getSampleModel(), + img.getColorModel(), + img.getSampleModel()); + + if (renderer == null) + { + throw new UnsupportedOperationException("couldn't find renderer"); + } + + renderer.filter(jpeg.getRaster(), img.getRaster()); + + return img; + */ + + return null; + } + + public Image createImage(URL url) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public boolean prepareImage(Image image, + int width, + int height, + ImageObserver observer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public int checkImage(Image image, + int width, + int height, + ImageObserver observer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public Image createImage(ImageProducer producer) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public Image createImage(byte[] imagedata, + int imageoffset, + int imagelength) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + /* + public PrintJob getPrintJob(Frame frame, + String jobtitle, + Properties props); + */ + + public void beep() + { + throw new UnsupportedOperationException("not implemented yet"); + } + + public Clipboard getSystemClipboard() + { + return null; // FIXME + } + + protected EventQueue getSystemEventQueueImpl() + { + return queue; + } + + XGraphicsConfiguration getDefaultXGraphicsConfiguration() + { + if (defaultConfig == null) + { + Screen screen = display.getDefaultScreen(); + Visual visual = screen.getRootVisual(); + defaultConfig = new XGraphicsConfiguration(visual); + + // ASSERT: + if (!defaultConfig.getVisual().getScreen().equals(screen)) + { + String msg = "screen of graphics configuration is not " + + "default screen"; + throw new Error(msg); + } + } + + return defaultConfig; + } + + + /* + public DragSourceContextPeer + createDragSourceContextPeer(DragGestureEvent dge) + throws InvalidDnDOperationException; + + public DragGestureRecognizer + createDragGestureRecognizer(Class abstractRecognizerClass, + DragSource ds, Component c, + int srcActions, DragGestureListener dgl) { + throw new UnsupportedOperationException("not implemented"); + } + */ + + + /* + public Map mapInputMethodHighlight(InputMethodHighlight highlight); + */ +} |