|
From: <ls...@us...> - 2008-07-17 10:12:47
|
Revision: 4304
http://jnode.svn.sourceforge.net/jnode/?rev=4304&view=rev
Author: lsantha
Date: 2008-07-17 10:12:06 +0000 (Thu, 17 Jul 2008)
Log Message:
-----------
New java.awt.Graphics implementation.
Modified Paths:
--------------
trunk/core/src/classpath/vm/java/awt/image/VMImageAPI.java
trunk/gui/src/awt/org/jnode/awt/JNodeGraphicsEnvironment.java
trunk/gui/src/awt/org/jnode/awt/VMImageAPIImpl.java
trunk/gui/src/awt/org/jnode/awt/image/JNodeBufferedImage.java
trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFramePeer.java
trunk/gui/src/awt/org/jnode/awt/swingpeers/SwingComponentPeer.java
Added Paths:
-----------
trunk/gui/src/awt/org/jnode/awt/GraphicsFactory.java
trunk/gui/src/awt/org/jnode/awt/JNodeSurfaceGraphics2D.java
trunk/gui/src/awt/org/jnode/awt/image/BufferedImageGraphics2D.java
trunk/gui/src/awt/org/jnode/awt/util/BasicGraphics.java
trunk/gui/src/awt/org/jnode/awt/util/BasicSurfaceGraphics.java
trunk/gui/src/awt/org/jnode/awt/util/SurfaceGraphics2D.java
Modified: trunk/core/src/classpath/vm/java/awt/image/VMImageAPI.java
===================================================================
--- trunk/core/src/classpath/vm/java/awt/image/VMImageAPI.java 2008-07-17 09:55:42 UTC (rev 4303)
+++ trunk/core/src/classpath/vm/java/awt/image/VMImageAPI.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -23,6 +23,7 @@
import java.awt.Graphics2D;
+//todo: is it useful?
/**
* @author Ewout Prangsma (ep...@us...)
*/
Added: trunk/gui/src/awt/org/jnode/awt/GraphicsFactory.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/GraphicsFactory.java (rev 0)
+++ trunk/gui/src/awt/org/jnode/awt/GraphicsFactory.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -0,0 +1,48 @@
+/*
+ * $
+ */
+package org.jnode.awt;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import org.jnode.awt.image.JNodeBufferedImageGraphics;
+import org.jnode.awt.image.BufferedImageGraphics2D;
+
+/**
+ * @author Levente S\u00e1ntha
+ */
+public abstract class GraphicsFactory {
+ public static GraphicsFactory instance;
+
+ public static GraphicsFactory getInstance() {
+ if (instance == null) {
+ instance = new NewGraphicsFactory();
+ }
+ return instance;
+ }
+
+ public abstract Graphics2D createGraphics(BufferedImage image);
+
+ public abstract Graphics2D createGraphics(JNodeGenericPeer<?, ?> peer);
+
+ private static class OldGraphicsFactory extends GraphicsFactory {
+ public Graphics2D createGraphics(BufferedImage image) {
+ return new JNodeBufferedImageGraphics(image);
+ }
+
+ public Graphics2D createGraphics(JNodeGenericPeer<?, ?> peer) {
+ return new JNodeGraphics(peer);
+ }
+
+ }
+
+ private static class NewGraphicsFactory extends GraphicsFactory {
+ public Graphics2D createGraphics(BufferedImage image) {
+ return new BufferedImageGraphics2D(image);
+ }
+
+ public Graphics2D createGraphics(JNodeGenericPeer<?, ?> peer) {
+ return new JNodeSurfaceGraphics2D(peer);
+ }
+ }
+}
Modified: trunk/gui/src/awt/org/jnode/awt/JNodeGraphicsEnvironment.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/JNodeGraphicsEnvironment.java 2008-07-17 09:55:42 UTC (rev 4303)
+++ trunk/gui/src/awt/org/jnode/awt/JNodeGraphicsEnvironment.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -35,7 +35,6 @@
import javax.naming.NamingException;
import org.apache.log4j.Logger;
import org.jnode.awt.font.FontManager;
-import org.jnode.awt.image.JNodeBufferedImageGraphics;
import org.jnode.awt.image.JNodeBufferedImageGraphics2D;
import org.jnode.driver.Device;
import org.jnode.driver.DeviceUtils;
@@ -57,13 +56,13 @@
private GraphicsDevice defaultDevice;
/**
- * @param image
+ * @param image the target image
* @return The graphics
* @see java.awt.GraphicsEnvironment#createGraphics(java.awt.image.BufferedImage)
*/
public Graphics2D createGraphics(BufferedImage image) {
return SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null ?
- new JNodeBufferedImageGraphics2D(image) : new JNodeBufferedImageGraphics(image);
+ new JNodeBufferedImageGraphics2D(image) : GraphicsFactory.getInstance().createGraphics(image);
/*
..future transition to SunGraphics2D based buffered image graphics
Copied: trunk/gui/src/awt/org/jnode/awt/JNodeSurfaceGraphics2D.java (from rev 4301, trunk/gui/src/awt/org/jnode/awt/JNodeGraphics.java)
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/JNodeSurfaceGraphics2D.java (rev 0)
+++ trunk/gui/src/awt/org/jnode/awt/JNodeSurfaceGraphics2D.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -0,0 +1,138 @@
+/*
+ * $Id$
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.awt;
+
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import org.jnode.awt.util.SurfaceGraphics2D;
+import org.jnode.driver.video.util.AbstractSurface;
+
+/**
+ * @author epr
+ */
+public class JNodeSurfaceGraphics2D extends SurfaceGraphics2D {
+
+ private final JNodeGenericPeer component;
+ private final JNodeToolkit toolkit;
+
+ /**
+ * Initialize a graphics for the given component
+ *
+ * @param component
+ */
+ public JNodeSurfaceGraphics2D(JNodeGenericPeer<?, ?> component) {
+// super(component.getToolkitImpl().getGraphics(), ((Component) component.getTargetComponent()).getWidth(),
+ // ((Component) component.getTargetComponent()).getHeight());
+ super((AbstractSurface) component.getToolkitImpl().getGraphics());
+ this.component = component;
+ this.toolkit = component.getToolkitImpl();
+ }
+
+ /**
+ * Initialize a graphics base on the given source.
+ *
+ * @param src
+ */
+ public JNodeSurfaceGraphics2D(JNodeSurfaceGraphics2D src) {
+ super(src);
+ this.component = src.component;
+ this.toolkit = src.toolkit;
+ }
+
+ /**
+ * @return The graphics
+ * @see java.awt.Graphics#create()
+ */
+ public Graphics create() {
+ return new JNodeSurfaceGraphics2D(this);
+ }
+
+ /**
+ * @param font
+ * @return The metrics
+ * @see java.awt.Graphics#getFontMetrics(java.awt.Font)
+ */
+ public FontMetrics getFontMetrics(Font font) {
+ return toolkit.getFontMetrics(font);
+ }
+
+ /**
+ * @return The configuration
+ * @see java.awt.Graphics2D#getDeviceConfiguration()
+ */
+ public GraphicsConfiguration getDeviceConfiguration() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ //----- preparing Graphics2D
+ /**
+ * Returns the color model of this Graphics object.
+ *
+ * @return the color model of this Graphics object
+ */
+ protected ColorModel getColorModel() {
+ return toolkit.getColorModel();
+ }
+
+ /**
+ * Returns a WritableRaster that is used by this class to perform the
+ * rendering in. It is not necessary that the target surface immediately
+ * reflects changes in the raster. Updates to the raster are notified via
+ * {@link #updateRaster}.
+ *
+ * @return the destination raster
+ */
+ protected WritableRaster getDestinationRaster() {
+ if (image == null)
+ image = new BufferedImage(((Component) component.getTargetComponent()).getWidth(),
+ ((Component) component.getTargetComponent()).getHeight(), BufferedImage.TYPE_INT_ARGB);
+ return image.getRaster();
+ }
+
+ private BufferedImage image;
+
+ /**
+ * Notifies the backend that the raster has changed in the specified
+ * rectangular area. The raster that is provided in this method is always
+ * the same as the one returned in {@link #getDestinationRaster}.
+ * Backends that reflect changes to this raster directly don't need to do
+ * anything here.
+ *
+ * @param raster the updated raster, identical to the raster returned
+ * by {@link #getDestinationRaster()}
+ * @param x the upper left corner of the updated region, X coordinate
+ * @param y the upper lef corner of the updated region, Y coordinate
+ * @param w the width of the updated region
+ * @param h the height of the updated region
+ */
+ protected void updateRaster(Raster raster, int x, int y, int w, int h) {
+ drawImage(image, 0, 0, null);
+ }
+}
Modified: trunk/gui/src/awt/org/jnode/awt/VMImageAPIImpl.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/VMImageAPIImpl.java 2008-07-17 09:55:42 UTC (rev 4303)
+++ trunk/gui/src/awt/org/jnode/awt/VMImageAPIImpl.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -24,7 +24,6 @@
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.VMImageAPI;
-import org.jnode.awt.image.JNodeBufferedImageGraphics;
/**
* @author Ewout Prangsma (ep...@us...)
@@ -32,7 +31,7 @@
public class VMImageAPIImpl implements VMImageAPI {
public Graphics2D createGraphics(BufferedImage image) {
- return new JNodeBufferedImageGraphics(image);
+ return GraphicsFactory.getInstance().createGraphics(image);
}
}
Copied: trunk/gui/src/awt/org/jnode/awt/image/BufferedImageGraphics2D.java (from rev 4301, trunk/gui/src/awt/org/jnode/awt/image/JNodeBufferedImageGraphics.java)
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/image/BufferedImageGraphics2D.java (rev 0)
+++ trunk/gui/src/awt/org/jnode/awt/image/BufferedImageGraphics2D.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -0,0 +1,89 @@
+/*
+ * $Id$
+ *
+ * JNode.org
+ * Copyright (C) 2003-2006 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.jnode.awt.image;
+
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.WritableRaster;
+import org.jnode.awt.util.SurfaceGraphics2D;
+
+/**
+ * @author epr
+ */
+public class BufferedImageGraphics2D extends SurfaceGraphics2D {
+
+ private final BufferedImage image;
+
+ /**
+ * @param image the target image
+ */
+ public BufferedImageGraphics2D(BufferedImage image) {
+ //super(new BufferedImageSurface(image), image.getWidth(), image.getHeight());
+ super(new BufferedImageSurface(image));
+ this.image = image;
+ }
+
+ /**
+ * @param src
+ */
+ public BufferedImageGraphics2D(BufferedImageGraphics2D src) {
+ super(src);
+ this.image = src.image;
+ }
+
+ /**
+ * @return The graphics
+ * @see java.awt.Graphics#create()
+ */
+ public Graphics create() {
+ return new BufferedImageGraphics2D(this);
+ }
+
+ /**
+ * @return The configuration
+ * @see java.awt.Graphics2D#getDeviceConfiguration()
+ */
+ public GraphicsConfiguration getDeviceConfiguration() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * Returns the color model of this Graphics object.
+ *
+ * @return the color model of this Graphics object
+ */
+ protected ColorModel getColorModel() {
+ return image.getColorModel();
+ }
+
+ /**
+ * Returns a WritableRaster that is used by this class to perform the rendering on.
+ *
+ * @return the destination raster
+ */
+ protected WritableRaster getDestinationRaster() {
+ return image.getRaster();
+ }
+}
Modified: trunk/gui/src/awt/org/jnode/awt/image/JNodeBufferedImage.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/image/JNodeBufferedImage.java 2008-07-17 09:55:42 UTC (rev 4303)
+++ trunk/gui/src/awt/org/jnode/awt/image/JNodeBufferedImage.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -28,6 +28,7 @@
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.util.Hashtable;
+import org.jnode.awt.GraphicsFactory;
/**
* @author epr
@@ -70,6 +71,6 @@
*/
public Graphics2D createGraphics() {
return SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null ?
- new JNodeBufferedImageGraphics2D(this) : new JNodeBufferedImageGraphics(this);
+ new JNodeBufferedImageGraphics2D(this) : GraphicsFactory.getInstance().createGraphics(this);
}
}
Modified: trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFramePeer.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFramePeer.java 2008-07-17 09:55:42 UTC (rev 4303)
+++ trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFramePeer.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -51,8 +51,8 @@
import java.awt.peer.FramePeer;
import org.apache.log4j.Logger;
import org.jnode.awt.JNodeGenericPeer;
-import org.jnode.awt.JNodeGraphics;
import org.jnode.awt.JNodeGraphics2D;
+import org.jnode.awt.GraphicsFactory;
import sun.awt.CausedFocusEvent;
/**
@@ -319,7 +319,7 @@
*/
public Graphics getGraphics() {
return SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null ?
- new JNodeGraphics2D(this) : new JNodeGraphics(this);
+ new JNodeGraphics2D(this) : GraphicsFactory.getInstance().createGraphics(this);
}
/**
Modified: trunk/gui/src/awt/org/jnode/awt/swingpeers/SwingComponentPeer.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/swingpeers/SwingComponentPeer.java 2008-07-17 09:55:42 UTC (rev 4303)
+++ trunk/gui/src/awt/org/jnode/awt/swingpeers/SwingComponentPeer.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -40,6 +40,7 @@
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
+import java.awt.event.MouseEvent;
import java.awt.event.PaintEvent;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
@@ -52,8 +53,8 @@
import java.security.PrivilegedAction;
import org.apache.log4j.Logger;
import org.jnode.awt.JNodeGenericPeer;
-import org.jnode.awt.JNodeGraphics;
import org.jnode.awt.JNodeGraphics2D;
+import org.jnode.awt.GraphicsFactory;
import sun.awt.CausedFocusEvent;
/**
@@ -170,7 +171,7 @@
final int width = peerComponent.getWidth();
final int height = peerComponent.getHeight();
Graphics g = SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null ?
- new JNodeGraphics2D(this) : new JNodeGraphics(this);
+ new JNodeGraphics2D(this) : GraphicsFactory.getInstance().createGraphics(this);
g.translate(x, y);
g.clipRect(0, 0, width, height);
@@ -225,8 +226,12 @@
//Point p = component.getLocationOnScreen();
//g.translate(p.x, p.y);
if (event.getID() == PaintEvent.PAINT) {
+ if (!(targetComponent instanceof java.awt.Window))
+ peerComponent.paint(g);
targetComponent.paint(g);
} else {
+ if (!(targetComponent instanceof java.awt.Window))
+ peerComponent.update(g);
targetComponent.update(g);
}
//g.translate(-p.x, -p.y);
@@ -242,13 +247,25 @@
switch (id) {
case PaintEvent.PAINT:
case PaintEvent.UPDATE: {
- //processPaintEvent((PaintEvent)event);
+ processPaintEvent((PaintEvent) event);
break;
}
default: {
if (event.getSource() == targetComponent) {
event.setSource(peerComponent);
}
+ if (event.getID() == MouseEvent.MOUSE_ENTERED) {
+ Object source = event.getSource();
+ if (source instanceof Component) {
+ Component comp = (Component) source;
+ Cursor cur = comp.getCursor();
+ if (cur != null) {
+ comp.setCursor(cur);
+ } else {
+ comp.setCursor(Cursor.getDefaultCursor());
+ }
+ }
+ }
((ISwingPeer<awtT>) peerComponent).processAWTEvent(event);
break;
}
@@ -289,8 +306,11 @@
}
public final void paint(Graphics g) {
- //peerComponent.paint(g);
- toolkit.postEvent(new PaintEvent(targetComponent, PaintEvent.PAINT, targetComponent.getBounds()));
+ if (!(targetComponent instanceof java.awt.Window)) {
+ peerComponent.paint(g);
+ targetComponent.paint(g);
+ } else
+ toolkit.postEvent(new PaintEvent(targetComponent, PaintEvent.PAINT, targetComponent.getBounds()));
}
// Deprecated
@@ -474,7 +494,12 @@
// Cursor
public final void updateCursorImmediately() {
- toolkit.updateCursor(peerComponent.getCursor());
+
+ Cursor cur = targetComponent.getCursor();
+// org.jnode.vm.Unsafe.debug("JNodeToolkit.updateCursor()-2 " + cur + " for " + targetComponent + "\n");
+// org.jnode.vm.Unsafe.debugStackTrace(100);
+ peerComponent.setCursor(cur);
+ toolkit.updateCursor(cur);
}
/**
Added: trunk/gui/src/awt/org/jnode/awt/util/BasicGraphics.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/util/BasicGraphics.java (rev 0)
+++ trunk/gui/src/awt/org/jnode/awt/util/BasicGraphics.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -0,0 +1,332 @@
+/*
+ * $
+ */
+package org.jnode.awt.util;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Levente S\u00e1ntha
+ */
+public abstract class BasicGraphics extends Graphics {
+ protected Rectangle clip;
+ protected Point origin = new Point();
+ protected Color color = Color.BLACK;
+ protected Font font = new Font("Luxi Sans", Font.PLAIN, 10);
+
+ protected BasicGraphics() {
+
+ }
+
+ protected BasicGraphics(BasicGraphics g) {
+ this.clip = g.clip.getBounds();
+ this.origin = g.origin.getLocation();
+ this.color = g.color;
+ this.font = g.font;
+ }
+
+ /**
+ * Intersects the current clip with the specified rectangle.
+ * The resulting clipping area is the intersection of the current
+ * clipping area and the specified rectangle. If there is no
+ * current clipping area, either because the clip has never been
+ * set, or the clip has been cleared using <code>setClip(null)</code>,
+ * the specified rectangle becomes the new clip.
+ * This method sets the user clip, which is independent of the
+ * clipping associated with device bounds and window visibility.
+ * This method can only be used to make the current clip smaller.
+ * To set the current clip larger, use any of the setClip methods.
+ * Rendering operations have no effect outside of the clipping area.
+ *
+ * @param x the x coordinate of the rectangle to intersect the clip with
+ * @param y the y coordinate of the rectangle to intersect the clip with
+ * @param width the width of the rectangle to intersect the clip with
+ * @param height the height of the rectangle to intersect the clip with
+ * @see #setClip(int, int, int, int)
+ * @see #setClip(java.awt.Shape)
+ */
+ public void clipRect(int x, int y, int width, int height) {
+ Rectangle r = new Rectangle(x, y, width, height);
+ _transform(r);
+ if (clip == null)
+ clip = r;
+ else
+ clip = clip.intersection(r);
+
+ if (this.clip.width == 0 && this.clip.height == 0) {
+ org.jnode.vm.Unsafe.debug("SimpleSurfaceGraphics: zero clip " + clip + "\n");
+ org.jnode.vm.Unsafe.debugStackTrace();
+ }
+ }
+
+ /**
+ * Disposes of this graphics context and releases
+ * any system resources that it is using.
+ * A <code>Graphics</code> object cannot be used after
+ * <code>dispose</code>has been called.
+ * <p/>
+ * When a Java program runs, a large number of <code>Graphics</code>
+ * objects can be created within a short time frame.
+ * Although the finalization process of the garbage collector
+ * also disposes of the same system resources, it is preferable
+ * to manually free the associated resources by calling this
+ * method rather than to rely on a finalization process which
+ * may not run to completion for a long period of time.
+ * <p/>
+ * Graphics objects which are provided as arguments to the
+ * <code>paint</code> and <code>update</code> methods
+ * of components are automatically released by the system when
+ * those methods return. For efficiency, programmers should
+ * call <code>dispose</code> when finished using
+ * a <code>Graphics</code> object only if it was created
+ * directly from a component or another <code>Graphics</code> object.
+ *
+ * @see java.awt.Graphics#finalize
+ * @see java.awt.Component#paint
+ * @see java.awt.Component#update
+ * @see java.awt.Component#getGraphics
+ * @see java.awt.Graphics#create
+ */
+ public void dispose() {
+
+ }
+
+ /**
+ * Gets the current clipping area.
+ * This method returns the user clip, which is independent of the
+ * clipping associated with device bounds and window visibility.
+ * If no clip has previously been set, or if the clip has been
+ * cleared using <code>setClip(null)</code>, this method returns
+ * <code>null</code>.
+ *
+ * @return a <code>Shape</code> object representing the
+ * current clipping area, or <code>null</code> if
+ * no clip is set.
+ * @see java.awt.Graphics#getClipBounds
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(int, int, int, int)
+ * @see java.awt.Graphics#setClip(java.awt.Shape)
+ * @since JDK1.1
+ */
+ public Shape getClip() {
+ if (clip == null)
+ return null;
+
+ Rectangle c = new Rectangle(clip);
+ i_transform(c);
+ return c;
+ }
+
+ /**
+ * Returns the bounding rectangle of the current clipping area.
+ * This method refers to the user clip, which is independent of the
+ * clipping associated with device bounds and window visibility.
+ * If no clip has previously been set, or if the clip has been
+ * cleared using <code>setClip(null)</code>, this method returns
+ * <code>null</code>.
+ * The coordinates in the rectangle are relative to the coordinate
+ * system origin of this graphics context.
+ *
+ * @return the bounding rectangle of the current clipping area,
+ * or <code>null</code> if no clip is set.
+ * @see java.awt.Graphics#getClip
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(int, int, int, int)
+ * @see java.awt.Graphics#setClip(java.awt.Shape)
+ * @since JDK1.1
+ */
+ public Rectangle getClipBounds() {
+ if (clip == null)
+ return null;
+
+ Rectangle c = new Rectangle(clip);
+ i_transform(c);
+ return c;
+ }
+
+ /**
+ * Gets this graphics context's current color.
+ *
+ * @return this graphics context's current color.
+ * @see java.awt.Color
+ * @see java.awt.Graphics#setColor(java.awt.Color)
+ */
+ public Color getColor() {
+ return color;
+ }
+
+ /**
+ * Gets the current font.
+ *
+ * @return this graphics context's current font.
+ * @see java.awt.Font
+ * @see java.awt.Graphics#setFont(java.awt.Font)
+ */
+ public Font getFont() {
+ return font;
+ }
+
+ /**
+ * Gets the font metrics for the specified font.
+ *
+ * @param f the specified font
+ * @return the font metrics for the specified font.
+ * @see java.awt.Graphics#getFont
+ * @see java.awt.FontMetrics
+ * @see java.awt.Graphics#getFontMetrics()
+ */
+ public FontMetrics getFontMetrics(Font f) {
+ return Toolkit.getDefaultToolkit().getFontMetrics(font);
+ }
+
+ /**
+ * Sets the current clipping area to an arbitrary clip shape.
+ * Not all objects that implement the <code>Shape</code>
+ * interface can be used to set the clip. The only
+ * <code>Shape</code> objects that are guaranteed to be
+ * supported are <code>Shape</code> objects that are
+ * obtained via the <code>getClip</code> method and via
+ * <code>Rectangle</code> objects. This method sets the
+ * user clip, which is independent of the clipping associated
+ * with device bounds and window visibility.
+ *
+ * @param clip the <code>Shape</code> to use to set the clip
+ * @see java.awt.Graphics#getClip()
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(int, int, int, int)
+ * @since JDK1.1
+ */
+ public void setClip(Shape clip) {
+ if (clip instanceof Rectangle) {
+ this.clip = new Rectangle((Rectangle) clip);
+ _transform(this.clip);
+ } else if (clip instanceof Rectangle2D) {
+ this.clip = clip.getBounds();
+ _transform(this.clip);
+ }
+ if (this.clip.width == 0 && this.clip.height == 0) {
+ org.jnode.vm.Unsafe.debug("SimpleSurfaceGraphics: zero clip " + clip + "\n");
+ org.jnode.vm.Unsafe.debugStackTrace();
+ }
+ }
+
+ /**
+ * Sets the current clip to the rectangle specified by the given
+ * coordinates. This method sets the user clip, which is
+ * independent of the clipping associated with device bounds
+ * and window visibility.
+ * Rendering operations have no effect outside of the clipping area.
+ *
+ * @param x the <i>x</i> coordinate of the new clip rectangle.
+ * @param y the <i>y</i> coordinate of the new clip rectangle.
+ * @param width the width of the new clip rectangle.
+ * @param height the height of the new clip rectangle.
+ * @see java.awt.Graphics#getClip
+ * @see java.awt.Graphics#clipRect
+ * @see java.awt.Graphics#setClip(java.awt.Shape)
+ * @since JDK1.1
+ */
+ public void setClip(int x, int y, int width, int height) {
+ this.clip = new Rectangle(x, y, width, height);
+ _transform(this.clip);
+ if (clip.width == 0 && clip.height == 0) {
+ org.jnode.vm.Unsafe.debug("SimpleSurfaceGraphics: zero clip " + clip + "\n");
+ org.jnode.vm.Unsafe.debugStackTrace();
+ }
+ }
+
+ /**
+ * Sets this graphics context's current color to the specified
+ * color. All subsequent graphics operations using this graphics
+ * context use this specified color.
+ *
+ * @param c the new rendering color.
+ * @see java.awt.Color
+ * @see java.awt.Graphics#getColor
+ */
+ public void setColor(Color c) {
+ if (c != null)
+ this.color = c;
+ }
+
+ /**
+ * Sets this graphics context's font to the specified font.
+ * All subsequent text operations using this graphics context
+ * use this font. A null argument is silently ignored.
+ *
+ * @param font the font.
+ * @see java.awt.Graphics#getFont
+ * @see java.awt.Graphics#drawString(String, int, int)
+ * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int)
+ * @see java.awt.Graphics#drawChars(char[], int, int, int, int)
+ */
+ public void setFont(Font font) {
+ if (font != null)
+ this.font = font;
+ }
+
+ /**
+ * Sets the paint mode of this graphics context to overwrite the
+ * destination with this graphics context's current color.
+ * This sets the logical pixel operation function to the paint or
+ * overwrite mode. All subsequent rendering operations will
+ * overwrite the destination with the current color.
+ */
+ public void setPaintMode() {
+ //todo
+ }
+
+ /**
+ * Sets the paint mode of this graphics context to alternate between
+ * this graphics context's current color and the new specified color.
+ * This specifies that logical pixel operations are performed in the
+ * XOR mode, which alternates pixels between the current color and
+ * a specified XOR color.
+ * <p/>
+ * When drawing operations are performed, pixels which are the
+ * current color are changed to the specified color, and vice versa.
+ * <p/>
+ * Pixels that are of colors other than those two colors are changed
+ * in an unpredictable but reversible manner; if the same figure is
+ * drawn twice, then all pixels are restored to their original values.
+ *
+ * @param c1 the XOR alternation color
+ */
+ public void setXORMode(Color c1) {
+ //todo
+ }
+
+ /**
+ * Translates the origin of the graphics context to the point
+ * (<i>x</i>, <i>y</i>) in the current coordinate system.
+ * Modifies this graphics context so that its new origin corresponds
+ * to the point (<i>x</i>, <i>y</i>) in this graphics context's
+ * original coordinate system. All coordinates used in subsequent
+ * rendering operations on this graphics context will be relative
+ * to this new origin.
+ *
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ */
+ public void translate(int x, int y) {
+ origin.translate(x, y);
+ }
+
+ protected void _transform(Rectangle r) {
+ r.x = r.x + origin.x;
+ r.y = r.y + origin.y;
+ }
+
+ protected void i_transform(Rectangle r) {
+ r.x = r.x - origin.x;
+ r.y = r.y - origin.y;
+ }
+}
Added: trunk/gui/src/awt/org/jnode/awt/util/BasicSurfaceGraphics.java
===================================================================
--- trunk/gui/src/awt/org/jnode/awt/util/BasicSurfaceGraphics.java (rev 0)
+++ trunk/gui/src/awt/org/jnode/awt/util/BasicSurfaceGraphics.java 2008-07-17 10:12:06 UTC (rev 4304)
@@ -0,0 +1,1037 @@
+/*
+ * $
+ */
+package org.jnode.awt.util;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.image.AreaAveragingScaleFilter;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.CropImageFilter;
+import java.awt.image.DirectColorModel;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageObserver;
+import java.awt.image.IndexColorModel;
+import java.awt.image.PixelGrabber;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.WritableRaster;
+import java.text.AttributedCharacterIterator;
+import org.jnode.awt.JNodeToolkit;
+import org.jnode.driver.video.Surface;
+import org.jnode.driver.video.util.AbstractSurface;
+import sun.awt.image.ToolkitImage;
+
+/**
+ * @author Levente S\u00e1ntha
+ */
+public class BasicSurfaceGraphics extends BasicGraphics {
+ private final AbstractSurface surface;
+ private int mode = Surface.PAINT_MODE;
+
+ protected BasicSurfaceGraphics(AbstractSurface surface) {
+ this.surface = surface;
+ }
+
+ protected BasicSurfaceGraphics(BasicSurfaceGraphics g) {
+ super(g);
+ this.surface = g.surface;
+ this.mode = g.mode;
+ }
+
+ /**
+ * Clears the specified rectangle by filling it with the background
+ * color of the current drawing surface. This operation does not
+ * use the current paint mode.
+ * <p/>
+ * Beginning with Java 1.1, the background color
+ * of offscreen images may be system dependent. Applications should
+ * use <code>setColor</code> followed by <code>fillRect</code> to
+ * ensure that an offscreen image is cleared to a specific color.
+ *
+ * @param x the <i>x</i> coordinate of the rectangle to clear.
+ * @param y the <i>y</i> coordinate of the rectangle to clear.
+ * @param width the width of the rectangle to clear.
+ * @param height the height of the rectangle to clear.
+ * @see java.awt.Graphics#fillRect(int, int, int, int)
+ * @see java.awt.Graphics#drawRect
+ * @see java.awt.Graphics#setColor(java.awt.Color)
+ * @see java.awt.Graphics#setPaintMode
+ * @see java.awt.Graphics#setXORMode(java.awt.Color)
+ */
+ public void clearRect(int x, int y, int width, int height) {
+ Rectangle r = new Rectangle(x, y, width, height);
+ _transform(r);
+ if (clip != null)
+ r = clip.intersection(r);
+
+ surface.fillRect(r.x, r.y, r.width, r.height, Color.BLACK.getRGB(), Surface.PAINT_MODE);
+ surface.update(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Copies an area of the component by a distance specified by
+ * <code>dx</code> and <code>dy</code>. From the point specified
+ * by <code>x</code> and <code>y</code>, this method
+ * copies downwards and to the right. To copy an area of the
+ * component to the left or upwards, specify a negative value for
+ * <code>dx</code> or <code>dy</code>.
+ * If a portion of the source rectangle lies outside the bounds
+ * of the component, or is obscured by another window or component,
+ * <code>copyArea</code> will be unable to copy the associated
+ * pixels. The area that is omitted can be refreshed by calling
+ * the component's <code>paint</code> method.
+ *
+ * @param x the <i>x</i> coordinate of the source rectangle.
+ * @param y the <i>y</i> coordinate of the source rectangle.
+ * @param width the width of the source rectangle.
+ * @param height the height of the source rectangle.
+ * @param dx the horizontal distance to copy the pixels.
+ * @param dy the vertical distance to copy the pixels.
+ */
+ public void copyArea(final int x, final int y, final int width, final int height,
+ final int dx, final int dy) {
+ //source area
+ Rectangle sr = new Rectangle(x, y, width, height);
+ _transform(sr);
+ if (clip != null)
+ sr = clip.intersection(sr);
+
+ //destination area
+ Rectangle dr = new Rectangle(x + dx, y + dy, width, height);
+ _transform(dr);
+ if (clip != null)
+ dr = clip.intersection(dr);
+
+ final int w = Math.min(sr.width, dr.width);
+ final int h = Math.min(sr.height, dr.height);
+
+ if (dr.x != sr.x + dx) sr.x = dr.x - dx;
+ if (dr.y != sr.y + dy) sr.y = dr.y - dy;
+
+
+ surface.copyArea(sr.x, sr.y, w, h, dx, dy);
+ }
+
+ /**
+ * Draws the outline of a circular or elliptical arc
+ * covering the specified rectangle.
+ * <p/>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees, using the current color.
+ * Angles are interpreted such that 0 degrees
+ * is at the 3 o'clock position.
+ * A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * <p/>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<i>x</i>, <i>y</i>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * <p/>
+ * The resulting arc covers an area
+ * <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * <p/>
+ * The angles are specified relative to the non-square extents of
+ * the bounding rectangle such that 45 degrees always falls on the
+ * line from the center of the ellipse to the upper right corner of
+ * the bounding rectangle. As a result, if the bounding rectangle is
+ * noticeably longer in one axis than the other, the angles to the
+ * start and end of the arc segment will be skewed farther along the
+ * longer axis of the bounds.
+ *
+ * @param x the <i>x</i> coordinate of the
+ * upper-left corner of the arc to be drawn.
+ * @param y the <i>y</i> coordinate of the
+ * upper-left corner of the arc to be drawn.
+ * @param width the width of the arc to be drawn.
+ * @param height the height of the arc to be drawn.
+ * @param startAngle the beginning angle.
+ * @param arcAngle the angular extent of the arc,
+ * relative to the start angle.
+ * @see java.awt.Graphics#fillArc
+ */
+ public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+ //todo implement it
+ org.jnode.vm.Unsafe.debug("SimpleSurfaceGraphics.drawArc() not implemented\n");
+ }
+
+ /**
+ * Draws as much of the specified area of the specified image as is
+ * currently available, scaling it on the fly to fit inside the
+ * specified area of the destination drawable surface. Transparent pixels
+ * do not affect whatever pixels are already there.
+ * <p/>
+ * This method returns immediately in all cases, even if the
+ * image area to be drawn has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that loads the image notifies
+ * the specified image observer.
+ * <p/>
+ * This method always uses the unscaled version of the image
+ * to render the scaled rectangle and performs the required
+ * scaling on the fly. It does not use a cached, scaled version
+ * of the image for this operation. Scaling of the image from source
+ * to destination is performed such that the first coordinate
+ * of the source rectangle is mapped to the first coordinate of
+ * the destination rectangle, and the second source coordinate is
+ * mapped to the second destination coordinate. The subimage is
+ * scaled and flipped as needed to preserve those mappings.
+ *
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param dx1 the <i>x</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dy1 the <i>y</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dx2 the <i>x</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param dy2 the <i>y</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param sx1 the <i>x</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sy1 the <i>y</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sx2 the <i>x</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param sy2 the <i>y</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param observer object to be notified as more of the image is
+ * scaled and converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ * @since JDK1.1
+ */
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
+ ImageObserver observer) {
+
+ return img == null || drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
+ }
+
+ /**
+ * Draws as much of the specified area of the specified image as is
+ * currently available, scaling it on the fly to fit inside the
+ * specified area of the destination drawable surface.
+ * <p/>
+ * Transparent pixels are drawn in the specified background color.
+ * This operation is equivalent to filling a rectangle of the
+ * width and height of the specified image with the given color and then
+ * drawing the image on top of it, but possibly more efficient.
+ * <p/>
+ * This method returns immediately in all cases, even if the
+ * image area to be drawn has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that loads the image notifies
+ * the specified image observer.
+ * <p/>
+ * This method always uses the unscaled version of the image
+ * to render the scaled rectangle and performs the required
+ * scaling on the fly. It does not use a cached, scaled version
+ * of the image for this operation. Scaling of the image from source
+ * to destination is performed such that the first coordinate
+ * of the source rectangle is mapped to the first coordinate of
+ * the destination rectangle, and the second source coordinate is
+ * mapped to the second destination coordinate. The subimage is
+ * scaled and flipped as needed to preserve those mappings.
+ *
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param dx1 the <i>x</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dy1 the <i>y</i> coordinate of the first corner of the
+ * destination rectangle.
+ * @param dx2 the <i>x</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param dy2 the <i>y</i> coordinate of the second corner of the
+ * destination rectangle.
+ * @param sx1 the <i>x</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sy1 the <i>y</i> coordinate of the first corner of the
+ * source rectangle.
+ * @param sx2 the <i>x</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param sy2 the <i>y</i> coordinate of the second corner of the
+ * source rectangle.
+ * @param bgcolor the background color to paint under the
+ * non-opaque portions of the image.
+ * @param observer object to be notified as more of the image is
+ * scaled and converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ * @since JDK1.1
+ */
+ 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) {
+ if (img == null) return true;
+
+ if (dx1 == dx2 || dy1 == dy2) {
+ return true;
+ }
+ if (sx1 == sx2 || sy1 == sy2) {
+ return true;
+ }
+
+ final int widthImage;
+ final int heightImage;
+ final int xImage;
+ final int yImage;
+ if (sx2 > sx1) {
+ widthImage = sx2 - sx1 + 1;
+ xImage = sx1;
+ } else {
+ widthImage = sx1 - sx2 + 1;
+ xImage = sx2;
+ }
+
+ if (sy2 > sy1) {
+ heightImage = sy2 - sy1 + 1;
+ yImage = sy1;
+ } else {
+ heightImage = sy1 - sy2 + 1;
+ yImage = sy2;
+ }
+
+ final int widthDest;
+ final int heightDest;
+ final int xDest;
+ final int yDest;
+ if (dx2 > dx1) {
+ widthDest = dx2 - dx1 + 1;
+ xDest = dx1;
+ } else {
+ widthDest = dx1 - dx2 + 1;
+ xDest = dx2;
+ }
+
+ if (dy2 > dy1) {
+ heightDest = dy2 - dy1 + 1;
+ yDest = dy1;
+ } else {
+ heightDest = dy1 - dy2 + 1;
+ yDest = dy2;
+ }
+
+ // Extract the image with a CropImageFilter
+ final Image imageArea = new ToolkitImage(new FilteredImageSource(img.getSource(),
+ new CropImageFilter(xImage, yImage, widthImage, heightImage)));
+
+ if (bgcolor == null) {
+ return drawImage(imageArea, xDest, yDest, widthDest, heightDest, observer);
+ } else {
+ return drawImage(imageArea, xDest, yDest, widthDest, heightDest, bgcolor, observer);
+ }
+ }
+
+ /**
+ * Draws as much of the specified image as is currently available.
+ * The image is drawn with its top-left corner at
+ * (<i>x</i>, <i>y</i>) in this graphics context's coordinate
+ * space. Transparent pixels are drawn in the specified
+ * background color.
+ * <p/>
+ * This operation is equivalent to filling a rectangle of the
+ * width and height of the specified image with the given color and then
+ * drawing the image on top of it, but possibly more efficient.
+ * <p/>
+ * This method returns immediately in all cases, even if the
+ * complete image has not yet been loaded, and it has not been dithered
+ * and converted for the current output device.
+ * <p/>
+ * If the image has completely loaded and its pixels are
+ * no longer being changed, then
+ * <code>drawImage</code> returns <code>true</code>.
+ * Otherwise, <code>drawImage</code> returns <code>false</code>
+ * and as more of
+ * the image becomes available
+ * or it is time to draw another frame of animation,
+ * the process that loads the image notifies
+ * the specified image observer.
+ *
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param bgcolor the background color to paint under the
+ * non-opaque portions of the image.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
+ if (img == null) return true;
+ try {
+ Raster rast = getCompatibleRaster(img);
+ Rectangle r = new Rectangle(x, y, rast.getWidth(), rast.getHeight());
+ _transform(r);
+ if (clip != null)
+ r = clip.intersection(r);
+
+ surface.drawCompatibleRaster(rast, 0, 0, r.x, r.y, r.width, r.height, bgcolor);
+ surface.update(r.x, r.y, r.width + 2, r.height + 2);
+ return true;
+ } catch (InterruptedException ie) {
+ return false;
+ }
+ }
+
+ /**
+ * Draws as much of the specified image as is currently available.
+ * The image is drawn with its top-left corner at
+ * (<i>x</i>, <i>y</i>) in this graphics context's coordinate
+ * space. Transparent pixels in the image do not affect whatever
+ * pixels are already there.
+ * <p/>
+ * This method returns immediately in all cases, even if the
+ * complete image has not yet been loaded, and it has not been dithered
+ * and converted for the current output device.
+ * <p/>
+ * If the image has completely loaded and its pixels are
+ * no longer being changed, then
+ * <code>drawImage</code> returns <code>true</code>.
+ * Otherwise, <code>drawImage</code> returns <code>false</code>
+ * and as more of
+ * the image becomes available
+ * or it is time to draw another frame of animation,
+ * the process that loads the image notifies
+ * the specified image observer.
+ *
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+ if (img == null) return true;
+ try {
+ Raster rast = getCompatibleRaster(img);
+ Rectangle r = new Rectangle(x, y, rast.getWidth(), rast.getHeight());
+ _transform(r);
+ if (clip != null)
+ r = clip.intersection(r);
+
+ surface.drawCompatibleRaster(rast, 0, 0, r.x, r.y, r.width, r.height, null);
+ surface.update(r.x, r.y, r.width + 2, r.height + 2);
+ return true;
+ } catch (InterruptedException ie) {
+ return false;
+ }
+ }
+
+ /**
+ * Draws as much of the specified image as has already been scaled
+ * to fit inside the specified rectangle.
+ * <p/>
+ * The image is drawn inside the specified rectangle of this
+ * graphics context's coordinate space, and is scaled if
+ * necessary. Transparent pixels are drawn in the specified
+ * background color.
+ * This operation is equivalent to filling a rectangle of the
+ * width and height of the specified image with the given color and then
+ * drawing the image on top of it, but possibly more efficient.
+ * <p/>
+ * This method returns immediately in all cases, even if the
+ * entire image has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that loads the image notifies
+ * the specified image observer.
+ * <p/>
+ * A scaled version of an image will not necessarily be
+ * available immediately just because an unscaled version of the
+ * image has been constructed for this output device. Each size of
+ * the image may be cached separately and generated from the original
+ * data in a separate image production sequence.
+ *
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param width the width of the rectangle.
+ * @param height the height of the rectangle.
+ * @param bgcolor the background color to paint under the
+ * non-opaque portions of the image.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
+ return img == null || drawImage(new ToolkitImage(new FilteredImageSource(img.getSource(),
+ new AreaAveragingScaleFilter(width, height))), x, y, bgcolor, observer);
+ }
+
+ /**
+ * Draws as much of the specified image as has already been scaled
+ * to fit inside the specified rectangle.
+ * <p/>
+ * The image is drawn inside the specified rectangle of this
+ * graphics context's coordinate space, and is scaled if
+ * necessary. Transparent pixels do not affect whatever pixels
+ * are already there.
+ * <p/>
+ * This method returns immediately in all cases, even if the
+ * entire image has not yet been scaled, dithered, and converted
+ * for the current output device.
+ * If the current output representation is not yet complete, then
+ * <code>drawImage</code> returns <code>false</code>. As more of
+ * the image becomes available, the process that loads the image notifies
+ * the image observer by calling its <code>imageUpdate</code> method.
+ * <p/>
+ * A scaled version of an image will not necessarily be
+ * available immediately just because an unscaled version of the
+ * image has been constructed for this output device. Each size of
+ * the image may be cached separately and generated from the original
+ * data in a separate image production sequence.
+ *
+ * @param img the specified image to be drawn. This method does
+ * nothing if <code>img</code> is null.
+ * @param x the <i>x</i> coordinate.
+ * @param y the <i>y</i> coordinate.
+ * @param width the width of the rectangle.
+ * @param height the height of the rectangle.
+ * @param observer object to be notified as more of
+ * the image is converted.
+ * @return <code>false</code> if the image pixels are still changing;
+ * <code>true</code> otherwise.
+ * @see java.awt.Image
+ * @see java.awt.image.ImageObserver
+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
+ */
+ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
+ return img == null || drawImage(new ToolkitImage(new FilteredImageSource(img.getSource(),
+ new AreaAveragingScaleFilter(width, height))), x, y, observer);
+ }
+
+ /**
+ * Draws a line, using the current color, between the points
+ * <code>(x1, y1)</code> and <code>(x2, y2)</code>
+ * in this graphics context's coordinate system.
+ *
+ * @param x1 the first point's <i>x</i> coordinate.
+ * @param y1 the first point's <i>y</i> coordinate.
+ * @param x2 the second point's <i>x</i> coordinate.
+ * @param y2 the second point's <i>y</i> coordinate.
+ */
+ public void drawLine(int x1, int y1, int x2, int y2) {
+ x1 += origin.x;
+ y1 += origin.y;
+ x2 += origin.x;
+ y2 += origin.y;
+
+ if (clip == null || (clip.contains(x1, y1) && clip.contains(x2, y2))) {
+ surface.drawLine(x1, y1, x2, y2, color.getRGB(), mode);
+ } else {
+ //todo optimize clipping
+ //copute clipped line coordinates with the Liang-Barsjky alogorithm
+ drawLineClipped(x1, x2, y1, y2);
+ }
+
+ if (x1 == x2) {
+ if (y1 == y2)
+ surface.update(x1, y1, 2, 2);
+ else if (y1 < y2)
+ surface.update(x1, y1, 2, y2 - y1 + 2);
+ else
+ surface.update(x1, y2, 2, y1 - y2 + 2);
+
+ } else if (y1 == y2) {
+ if (x1 < x2)
+ surface.update(x1, y1, x2 - x1 + 2, 2);
+ else
+ surface.update(x2, y1, x1 - x2 + 2, 2);
+ } else {
+ if (x1 < x2 && y1 < y2)
+ surface.update(x1, y1, x2 - x1 + 2, y2 - y1 + 2);
+ else if (x1 < x2 && y1 > y2)
+ surface.update(x1, y2, x2 - x1 + 2, y1 - y2 + 2);
+ else if (x1 > x2 && y1 < y2)
+ surface.update(x2, y1, x1 - x2 + 2, y2 - y1 + 2);
+ else if (x1 > x2 && y1 > y2)
+ surface.update(x2, y2, x1 - x2 + 2, y1 - y2 + 2);
+ }
+ }
+
+ private void drawLineClipped(int x1, int x2, int y1, int y2) {
+ final int incx, incy;
+ int countx, county;
+
+ final int sizex = Math.abs(x2 - x1);
+ final int sizey = Math.abs(y2 - y1);
+ if (x1 > x2) {
+ incx = -1;
+ } else {
+ incx = 1;
+ }
+ if (y1 > y2) {
+ incy = -1;
+ } else {
+ incy = 1;
+ }
+ countx = x1;
+ county = y1;
+
+ drawPixelClipped(x1, y1);
+ if (sizex >= sizey) {
+ int y = sizex >> 1;
+ final int loops = sizex;
+ for (int i = 0; i < loops; i++) {
+ y += sizey;
+ if (y >= sizex) {
+ y -= sizex;
+ county += incy;
+ }
+ countx += incx;
+ drawPixelClipped(countx, county);
+ }
+ } else {
+ int x = sizey >> 1;
+ final int loops = sizey;
+ for (int i = 0; i < loops; i++) {
+ x += sizex;
+ if (x >= sizey) {
+ x -= sizey;
+ countx += incx;
+ }
+ county += incy;
+ drawPixelClipped(countx, county);
+ }
+ }
+ }
+
+ private void drawPixelClipped(int x, int y) {
+ if (clip == null || clip.contains(x, y))
+ surface.drawPixel(x, y,...
[truncated message content] |