summaryrefslogtreecommitdiff
path: root/gnu/java/awt/peer
diff options
context:
space:
mode:
authorGuilhem Lavaux <guilhem@kaffe.org>2006-07-09 16:59:05 +0000
committerGuilhem Lavaux <guilhem@kaffe.org>2006-07-09 16:59:05 +0000
commit8f2887fc8c74aae0d541cbd59ea36c37d420267d (patch)
treeadfecf70948384fcc6aa9cae41103dc4551d1b53 /gnu/java/awt/peer
parent4714fb23de2d811f49438611ac0d13ccd302e1ea (diff)
downloadclasspath-8f2887fc8c74aae0d541cbd59ea36c37d420267d.tar.gz
2006-07-09 Guilhem Lavaux <guilhem@kaffe.org>
* Merged HEAD as of 2006-06-09 0:00.
Diffstat (limited to 'gnu/java/awt/peer')
-rw-r--r--gnu/java/awt/peer/ClasspathTextLayoutPeer.java104
-rw-r--r--gnu/java/awt/peer/gtk/CairoGraphics2D.java541
-rw-r--r--gnu/java/awt/peer/gtk/CairoSurface.java119
-rw-r--r--gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java5
-rw-r--r--gnu/java/awt/peer/gtk/ComponentGraphics.java258
-rw-r--r--gnu/java/awt/peer/gtk/FreetypeGlyphVector.java504
-rw-r--r--gnu/java/awt/peer/gtk/GdkFontPeer.java74
-rw-r--r--gnu/java/awt/peer/gtk/GdkGlyphVector.java359
-rw-r--r--gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java40
-rw-r--r--gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java50
-rw-r--r--gnu/java/awt/peer/gtk/GdkPixbufDecoder.java107
-rw-r--r--gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java282
-rw-r--r--gnu/java/awt/peer/gtk/GdkTextLayout.java393
-rw-r--r--gnu/java/awt/peer/gtk/GtkCheckboxPeer.java164
-rw-r--r--gnu/java/awt/peer/gtk/GtkComponentPeer.java8
-rw-r--r--gnu/java/awt/peer/gtk/GtkLabelPeer.java8
-rw-r--r--gnu/java/awt/peer/gtk/GtkToolkit.java94
-rw-r--r--gnu/java/awt/peer/gtk/GtkVolatileImage.java53
-rw-r--r--gnu/java/awt/peer/gtk/VolatileImageGraphics.java80
-rw-r--r--gnu/java/awt/peer/qt/QtGraphics.java13
-rw-r--r--gnu/java/awt/peer/qt/QtToolkit.java15
-rw-r--r--gnu/java/awt/peer/swing/SwingComponentPeer.java76
-rw-r--r--gnu/java/awt/peer/x/GLGraphics.java123
-rw-r--r--gnu/java/awt/peer/x/ImageConverter.java113
-rw-r--r--gnu/java/awt/peer/x/KeyboardMapping.java415
-rw-r--r--gnu/java/awt/peer/x/XEventPump.java287
-rw-r--r--gnu/java/awt/peer/x/XFontPeer.java740
-rw-r--r--gnu/java/awt/peer/x/XFontPeer2.java335
-rw-r--r--gnu/java/awt/peer/x/XFramePeer.java321
-rw-r--r--gnu/java/awt/peer/x/XGraphics.java855
-rw-r--r--gnu/java/awt/peer/x/XGraphics2D.java295
-rw-r--r--gnu/java/awt/peer/x/XGraphicsConfiguration.java118
-rw-r--r--gnu/java/awt/peer/x/XGraphicsDevice.java166
-rw-r--r--gnu/java/awt/peer/x/XGraphicsEnvironment.java202
-rw-r--r--gnu/java/awt/peer/x/XImage.java107
-rw-r--r--gnu/java/awt/peer/x/XLightweightPeer.java (renamed from gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java)56
-rw-r--r--gnu/java/awt/peer/x/XToolkit.java575
-rw-r--r--gnu/java/awt/peer/x/XWindowPeer.java256
-rw-r--r--gnu/java/awt/peer/x/fonts.properties25
39 files changed, 6967 insertions, 1369 deletions
diff --git a/gnu/java/awt/peer/ClasspathTextLayoutPeer.java b/gnu/java/awt/peer/ClasspathTextLayoutPeer.java
deleted file mode 100644
index 70df2ef74..000000000
--- a/gnu/java/awt/peer/ClasspathTextLayoutPeer.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/* ClasspathTextLayoutPeer.java
- Copyright (C) 2003 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.java.awt.peer;
-
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.font.TextHitInfo;
-import java.awt.font.TextLayout;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-
-/**
- * @author Graydon Hoare
- */
-
-public interface ClasspathTextLayoutPeer
-{
- TextHitInfo getStrongCaret (TextHitInfo hit1,
- TextHitInfo hit2);
-
- void draw (Graphics2D g2, float x, float y);
-
- byte getBaseline ();
-
- boolean isLeftToRight ();
- boolean isVertical ();
-
- float getAdvance ();
- float getAscent ();
- float getDescent ();
- float getLeading ();
-
- int getCharacterCount ();
- byte getCharacterLevel (int index);
-
- float[] getBaselineOffsets ();
- Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint);
- Rectangle2D getBounds ();
-
- float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds);
- Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds);
- Shape[] getCaretShapes (int offset, Rectangle2D bounds,
- TextLayout.CaretPolicy policy);
-
- Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
- Rectangle2D bounds);
- int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
- TextHitInfo secondEndpoint);
-
- TextHitInfo getNextLeftHit (int offset, TextLayout.CaretPolicy policy);
- TextHitInfo getNextRightHit (int offset, TextLayout.CaretPolicy policy);
- TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds);
- TextHitInfo getVisualOtherHit (TextHitInfo hit);
-
- float getVisibleAdvance ();
- Shape getOutline (AffineTransform tx);
- Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
- TextHitInfo secondEndpoint,
- Rectangle2D bounds);
-
- TextLayout getJustifiedLayout (float justificationWidth);
- void handleJustify (float justificationWidth);
-
- Object clone ();
- int hashCode ();
- boolean equals (ClasspathTextLayoutPeer tl);
- String toString ();
-}
diff --git a/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
index dfebd995b..61871ccbc 100644
--- a/gnu/java/awt/peer/gtk/CairoGraphics2D.java
+++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -38,14 +38,13 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import gnu.classpath.Configuration;
import gnu.java.awt.ClasspathToolkit;
import java.awt.AlphaComposite;
+import java.awt.AWTPermission;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
-import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
@@ -63,9 +62,10 @@ import java.awt.TexturePaint;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
+import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
-import java.awt.geom.Line2D;
+import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.PathIterator;
@@ -76,12 +76,11 @@ import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;
-import java.awt.image.CropImageFilter;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
-import java.awt.image.FilteredImageSource;
import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
import java.awt.image.ImagingOpException;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
@@ -93,7 +92,6 @@ import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
import java.util.HashMap;
import java.util.Map;
-import java.util.Stack;
/**
* This is an abstract implementation of Graphics2D on Cairo.
@@ -240,13 +238,10 @@ public abstract class CairoGraphics2D extends Graphics2D
bg = new Color(g.bg.getRGB());
}
- if (g.clip == null)
- clip = null;
- else
- clip = new Rectangle(g.getClipBounds());
+ clip = g.getClip();
if (g.transform == null)
- transform = new AffineTransform();
+ transform = null;
else
transform = new AffineTransform(g.transform);
@@ -256,7 +251,8 @@ public abstract class CairoGraphics2D extends Graphics2D
setBackground(bg);
setPaint(paint);
setStroke(stroke);
- setTransform(transform);
+ setTransformImpl(transform);
+ setClip(clip);
}
/**
@@ -274,8 +270,8 @@ public abstract class CairoGraphics2D extends Graphics2D
* they have additional native structures.
*/
public void dispose()
- {
- disposeNative();
+ {
+ disposeNative(nativePointer);
nativePointer = 0;
}
@@ -303,7 +299,7 @@ public abstract class CairoGraphics2D extends Graphics2D
/**
* Dispose of allocate native resouces.
*/
- public native void disposeNative();
+ public native void disposeNative(long pointer);
/**
* Draw pixels as an RGBA int matrix
@@ -311,119 +307,165 @@ public abstract class CairoGraphics2D extends Graphics2D
* @param stride - stride of the array width
* @param i2u - affine transform array
*/
- private native void drawPixels(int[] pixels, int w, int h, int stride,
- double[] i2u);
+ private native void drawPixels(long pointer, int[] pixels, int w, int h,
+ int stride, double[] i2u, double alpha);
- private native void setGradient(double x1, double y1, double x2, double y2,
+ private native void setGradient(long pointer, double x1, double y1,
+ double x2, double y2,
int r1, int g1, int b1, int a1, int r2,
int g2, int b2, int a2, boolean cyclic);
- private native void setTexturePixels(int[] pixels, int w, int h, int stride);
+ private native void setTexturePixels(long pointer, int[] pixels, int w,
+ int h, int stride);
/**
* Set the current transform matrix
*/
- private native void cairoSetMatrix(double[] m);
+ private native void cairoSetMatrix(long pointer, double[] m);
/**
* Set the compositing operator
*/
- private native void cairoSetOperator(int cairoOperator);
+ private native void cairoSetOperator(long pointer, int cairoOperator);
/**
* Sets the current color in RGBA as a 0.0-1.0 double
*/
- private native void cairoSetRGBAColor(double red, double green,
+ private native void cairoSetRGBAColor(long pointer, double red, double green,
double blue, double alpha);
/**
* Sets the current winding rule in Cairo
*/
- private native void cairoSetFillRule(int cairoFillRule);
+ private native void cairoSetFillRule(long pointer, int cairoFillRule);
/**
* Set the line style, cap, join and miter limit.
* Cap and join parameters are in the BasicStroke enumerations.
*/
- private native void cairoSetLine(double width, int cap, int join, double miterLimit);
+ private native void cairoSetLine(long pointer, double width, int cap,
+ int join, double miterLimit);
/**
* Set the dash style
*/
- private native void cairoSetDash(double[] dashes, int ndash, double offset);
+ private native void cairoSetDash(long pointer, double[] dashes, int ndash,
+ double offset);
/*
* Draws a Glyph Vector
*/
- native void cairoDrawGlyphVector(GdkFontPeer font,
+ native void cairoDrawGlyphVector(long pointer, GdkFontPeer font,
float x, float y, int n,
int[] codes, float[] positions);
- private native void cairoRelCurveTo(double dx1, double dy1, double dx2,
- double dy2, double dx3, double dy3);
+ private native void cairoRelCurveTo(long pointer, double dx1, double dy1,
+ double dx2, double dy2, double dx3,
+ double dy3);
/**
* Appends a rectangle to the current path
*/
- private native void cairoRectangle(double x, double y, double width,
- double height);
+ private native void cairoRectangle(long pointer, double x, double y,
+ double width, double height);
/**
* New current path
*/
- private native void cairoNewPath();
+ private native void cairoNewPath(long pointer);
/**
* Close current path
*/
- private native void cairoClosePath();
+ private native void cairoClosePath(long pointer);
/** moveTo */
- private native void cairoMoveTo(double x, double y);
+ private native void cairoMoveTo(long pointer, double x, double y);
/** relative moveTo */
- private native void cairoRelMoveTo(double dx, double dy);
+ private native void cairoRelMoveTo(long pointer, double dx, double dy);
/** lineTo */
- private native void cairoLineTo(double x, double y);
+ private native void cairoLineTo(long pointer, double x, double y);
/** relative lineTo */
- private native void cairoRelLineTo(double dx, double dy);
+ private native void cairoRelLineTo(long pointer, double dx, double dy);
/** Cubic curve-to */
- private native void cairoCurveTo(double x1, double y1, double x2, double y2,
+ private native void cairoCurveTo(long pointer, double x1, double y1,
+ double x2, double y2,
double x3, double y3);
/**
* Stroke current path
*/
- private native void cairoStroke();
+ private native void cairoStroke(long pointer);
/**
* Fill current path
*/
- private native void cairoFill();
+ private native void cairoFill(long pointer, double alpha);
/**
* Clip current path
*/
- private native void cairoClip();
+ private native void cairoClip(long pointer);
/**
* Save clip
*/
- private native void cairoPreserveClip();
+ private native void cairoPreserveClip(long pointer);
/**
* Save clip
*/
- private native void cairoResetClip();
+ private native void cairoResetClip(long pointer);
/**
* Set interpolation types
*/
- private native void cairoSurfaceSetFilter(int filter);
+ private native void cairoSurfaceSetFilter(long pointer, int filter);
+
+ /**
+ * Draws a line from (x1,y1) to (x2,y2).
+ *
+ * @param pointer the native pointer
+ *
+ * @param x1 the x coordinate of the starting point
+ * @param y1 the y coordinate of the starting point
+ * @param x2 the x coordinate of the end point
+ * @param y2 the y coordinate of the end point
+ */
+ private native void cairoDrawLine(long pointer, double x1, double y1,
+ double x2, double y2);
+
+ /**
+ * Draws a rectangle at starting point (x,y) and with the specified width
+ * and height.
+ *
+ * @param pointer the native pointer
+ * @param x the x coordinate of the upper left corner
+ * @param y the y coordinate of the upper left corner
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ */
+ private native void cairoDrawRect(long pointer, double x, double y, double w,
+ double h);
+
+ /**
+ * Fills a rectangle at starting point (x,y) and with the specified width
+ * and height.
+ *
+ * @param pointer the native pointer
+ * @param x the x coordinate of the upper left corner
+ * @param y the y coordinate of the upper left corner
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ */
+ private native void cairoFillRect(long pointer, double x, double y, double w,
+ double h);
+
///////////////////////// TRANSFORMS ///////////////////////////////////
/**
@@ -431,43 +473,60 @@ public abstract class CairoGraphics2D extends Graphics2D
*/
public void setTransform(AffineTransform tx)
{
+ // Transform clip into target space using the old transform.
+ updateClip(transform);
+
+ // Update the native transform.
+ setTransformImpl(tx);
+
+ // Transform the clip back into user space using the inverse new transform.
+ try
+ {
+ updateClip(transform.createInverse());
+ }
+ catch (NoninvertibleTransformException ex)
+ {
+ // TODO: How can we deal properly with this?
+ ex.printStackTrace();
+ }
+
+ if (clip != null)
+ setClip(clip);
+ }
+
+ private void setTransformImpl(AffineTransform tx)
+ {
transform = tx;
if (transform != null)
{
- double[] m = new double[6];
- transform.getMatrix(m);
- cairoSetMatrix(m);
+ double[] m = new double[6];
+ transform.getMatrix(m);
+ cairoSetMatrix(nativePointer, m);
}
}
-
+
public void transform(AffineTransform tx)
{
if (transform == null)
transform = new AffineTransform(tx);
else
transform.concatenate(tx);
- setTransform(transform);
+
if (clip != null)
{
- // FIXME: this should actuall try to transform the shape
- // rather than degrade to bounds.
- Rectangle2D r = clip.getBounds2D();
- double[] coords = new double[]
- {
- r.getX(), r.getY(), r.getX() + r.getWidth(),
- r.getY() + r.getHeight()
- };
- try
- {
- tx.createInverse().transform(coords, 0, coords, 0, 2);
- r.setRect(coords[0], coords[1], coords[2] - coords[0],
- coords[3] - coords[1]);
- clip = r;
- }
- catch (java.awt.geom.NoninvertibleTransformException e)
- {
- }
+ try
+ {
+ AffineTransform clipTransform = tx.createInverse();
+ updateClip(clipTransform);
+ }
+ catch (NoninvertibleTransformException ex)
+ {
+ // TODO: How can we deal properly with this?
+ ex.printStackTrace();
+ }
}
+
+ setTransformImpl(transform);
}
public void rotate(double theta)
@@ -500,18 +559,21 @@ public abstract class CairoGraphics2D extends Graphics2D
{
// FIXME: this should actuall try to transform the shape
// rather than degrade to bounds.
- Rectangle2D r;
-
if (clip instanceof Rectangle2D)
- r = (Rectangle2D) clip;
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ r.setRect(r.getX() - tx, r.getY() - ty, r.getWidth(),
+ r.getHeight());
+ }
else
- r = clip.getBounds2D();
-
- r.setRect(r.getX() - tx, r.getY() - ty, r.getWidth(), r.getHeight());
- clip = r;
+ {
+ AffineTransform clipTransform =
+ AffineTransform.getTranslateInstance(-tx, -ty);
+ updateClip(clipTransform);
+ }
}
- setTransform(transform);
+ setTransformImpl(transform);
}
public void translate(int x, int y)
@@ -528,10 +590,50 @@ public abstract class CairoGraphics2D extends Graphics2D
public void clip(Shape s)
{
- if( s == null )
- setClip( originalClip );
+ // Do not touch clip when s == null.
+ if (s == null)
+ {
+ // The spec says this should clear the clip. The reference
+ // implementation throws a NullPointerException instead. I think,
+ // in this case we should conform to the specs, as it shouldn't
+ // affect compatibility.
+ setClip(null);
+ return;
+ }
- setClip(s);
+ // If the current clip is still null, initialize it.
+ if (clip == null)
+ {
+ clip = getRealBounds();
+ }
+
+ // This is so common, let's optimize this.
+ if (clip instanceof Rectangle2D && s instanceof Rectangle2D)
+ {
+ Rectangle2D clipRect = (Rectangle2D) clip;
+ Rectangle2D r = (Rectangle2D) s;
+ Rectangle2D.intersect(clipRect, r, clipRect);
+ setClip(clipRect);
+ }
+ else
+ {
+ Area current;
+ if (clip instanceof Area)
+ current = (Area) clip;
+ else
+ current = new Area(clip);
+
+ Area intersect;
+ if (s instanceof Area)
+ intersect = (Area) s;
+ else
+ intersect = new Area(s);
+
+ current.intersect(intersect);
+ clip = current;
+ // Call setClip so that the native side gets notified.
+ setClip(clip);
+ }
}
public Paint getPaint()
@@ -570,7 +672,7 @@ public abstract class CairoGraphics2D extends Graphics2D
AffineTransformOp op = new AffineTransformOp(at, getRenderingHints());
BufferedImage texture = op.filter(img, null);
int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width);
- setTexturePixels(pixels, width, height, width);
+ setTexturePixels(nativePointer, pixels, width, height, width);
}
else if (paint instanceof GradientPaint)
{
@@ -579,9 +681,10 @@ public abstract class CairoGraphics2D extends Graphics2D
Point2D p2 = gp.getPoint2();
Color c1 = gp.getColor1();
Color c2 = gp.getColor2();
- setGradient(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c1.getRed(),
- c1.getGreen(), c1.getBlue(), c1.getAlpha(), c2.getRed(),
- c2.getGreen(), c2.getBlue(), c2.getAlpha(), gp.isCyclic());
+ setGradient(nativePointer, p1.getX(), p1.getY(), p2.getX(), p2.getY(),
+ c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha(),
+ c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha(),
+ gp.isCyclic());
}
else
throw new java.lang.UnsupportedOperationException();
@@ -598,7 +701,7 @@ public abstract class CairoGraphics2D extends Graphics2D
if (stroke instanceof BasicStroke)
{
BasicStroke bs = (BasicStroke) stroke;
- cairoSetLine(bs.getLineWidth(), bs.getEndCap(),
+ cairoSetLine(nativePointer, bs.getLineWidth(), bs.getEndCap(),
bs.getLineJoin(), bs.getMiterLimit());
float[] dashes = bs.getDashArray();
@@ -607,11 +710,11 @@ public abstract class CairoGraphics2D extends Graphics2D
double[] double_dashes = new double[dashes.length];
for (int i = 0; i < dashes.length; i++)
double_dashes[i] = dashes[i];
- cairoSetDash(double_dashes, double_dashes.length,
+ cairoSetDash(nativePointer, double_dashes, double_dashes.length,
(double) bs.getDashPhase());
}
else
- cairoSetDash(new double[0], 0, 0.0);
+ cairoSetDash(nativePointer, new double[0], 0, 0.0);
}
}
@@ -642,8 +745,9 @@ public abstract class CairoGraphics2D extends Graphics2D
{
if (fg == null)
fg = Color.BLACK;
- cairoSetRGBAColor(fg.getRed() / 255.0, fg.getGreen() / 255.0,
- fg.getBlue() / 255.0, fg.getAlpha() / 255.0);
+ cairoSetRGBAColor(nativePointer, fg.getRed() / 255.0,
+ fg.getGreen() / 255.0,fg.getBlue() / 255.0,
+ fg.getAlpha() / 255.0);
}
public Color getColor()
@@ -653,15 +757,30 @@ public abstract class CairoGraphics2D extends Graphics2D
public void clipRect(int x, int y, int width, int height)
{
- clip(new Rectangle(x, y, width, height));
+ if (clip == null)
+ setClip(new Rectangle(x, y, width, height));
+ else if (clip instanceof Rectangle)
+ {
+ computeIntersection(x, y, width, height, (Rectangle) clip);
+ setClip(clip);
+ }
+ else
+ clip(new Rectangle(x, y, width, height));
}
public Shape getClip()
{
if (clip == null)
return null;
- else
+ else if (clip instanceof Rectangle2D)
return clip.getBounds2D(); //getClipInDevSpace();
+ else
+ {
+ GeneralPath p = new GeneralPath();
+ PathIterator pi = clip.getPathIterator(null);
+ p.append(pi, false);
+ return p;
+ }
}
public Rectangle getClipBounds()
@@ -701,7 +820,7 @@ public abstract class CairoGraphics2D extends Graphics2D
}
public void setClip(Shape s)
- {
+ {
// The first time the clip is set, save it as the original clip
// to reset to on s == null. We can rely on this being non-null
// because the constructor in subclasses is expected to set the
@@ -712,23 +831,23 @@ public abstract class CairoGraphics2D extends Graphics2D
firstClip = false;
}
- if (s == null)
- clip = originalClip;
- else
- clip = s;
-
- cairoResetClip();
+ clip = s;
+ cairoResetClip(nativePointer);
- cairoNewPath();
- if (clip instanceof Rectangle2D)
+ if (clip != null)
{
- Rectangle2D r = (Rectangle2D) clip;
- cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ cairoNewPath(nativePointer);
+ if (clip instanceof Rectangle2D)
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ cairoRectangle(nativePointer, r.getX(), r.getY(), r.getWidth(),
+ r.getHeight());
+ }
+ else
+ walkPath(clip.getPathIterator(null), false);
+
+ cairoClip(nativePointer);
}
- else
- walkPath(clip.getPathIterator(null), false);
-
- cairoClip();
}
public void setBackground(Color c)
@@ -764,13 +883,16 @@ public abstract class CairoGraphics2D extends Graphics2D
if (comp instanceof AlphaComposite)
{
AlphaComposite a = (AlphaComposite) comp;
- cairoSetOperator(a.getRule());
- Color c = getColor();
- setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(),
- (int) (a.getAlpha() * ((float) c.getAlpha()))));
+ cairoSetOperator(nativePointer, a.getRule());
}
else
{
+ // FIXME: this check is only required "if this Graphics2D
+ // context is drawing to a Component on the display screen".
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AWTPermission("readDisplayPixels"));
+
// FIXME: implement general Composite support
throw new java.lang.UnsupportedOperationException();
}
@@ -780,38 +902,54 @@ public abstract class CairoGraphics2D extends Graphics2D
public void draw(Shape s)
{
- if (stroke != null && ! (stroke instanceof BasicStroke))
+ if ((stroke != null && ! (stroke instanceof BasicStroke))
+ || (comp instanceof AlphaComposite
+ && ((AlphaComposite) comp).getAlpha() != 1.0))
{
+ // FIXME: This is a hack to work around BasicStrokes's current
+ // limitations wrt cubic curves.
+ // See CubicSegment.getDisplacedSegments().
+ if (stroke instanceof BasicStroke)
+ {
+ PathIterator flatten = s.getPathIterator(null, 1.0);
+ GeneralPath p = new GeneralPath();
+ p.append(flatten, false);
+ s = p;
+ }
fill(stroke.createStrokedShape(s));
return;
}
- cairoNewPath();
+ cairoNewPath(nativePointer);
if (s instanceof Rectangle2D)
{
Rectangle2D r = (Rectangle2D) s;
- cairoRectangle(shifted(r.getX(), shiftDrawCalls),
+ cairoRectangle(nativePointer, shifted(r.getX(), shiftDrawCalls),
shifted(r.getY(), shiftDrawCalls), r.getWidth(),
r.getHeight());
}
else
walkPath(s.getPathIterator(null), shiftDrawCalls);
- cairoStroke();
+ cairoStroke(nativePointer);
}
public void fill(Shape s)
{
- cairoNewPath();
+ cairoNewPath(nativePointer);
if (s instanceof Rectangle2D)
{
Rectangle2D r = (Rectangle2D) s;
- cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ cairoRectangle(nativePointer, r.getX(), r.getY(), r.getWidth(),
+ r.getHeight());
}
else
walkPath(s.getPathIterator(null), false);
- cairoFill();
+ double alpha = 1.0;
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+ cairoFill(nativePointer, alpha);
}
/**
@@ -823,8 +961,8 @@ public abstract class CairoGraphics2D extends Graphics2D
public void clearRect(int x, int y, int width, int height)
{
if (bg != null)
- cairoSetRGBAColor(bg.getRed() / 255.0, bg.getGreen() / 255.0,
- bg.getBlue() / 255.0, 1.0);
+ cairoSetRGBAColor(nativePointer, bg.getRed() / 255.0,
+ bg.getGreen() / 255.0, bg.getBlue() / 255.0, 1.0);
fillRect(x, y, width, height);
updateColor();
}
@@ -847,12 +985,15 @@ public abstract class CairoGraphics2D extends Graphics2D
public void drawLine(int x1, int y1, int x2, int y2)
{
- draw(new Line2D.Double(x1, y1, x2, y2));
+ cairoDrawLine(nativePointer, shifted(x1, shiftDrawCalls),
+ shifted(y1, shiftDrawCalls), shifted(x2, shiftDrawCalls),
+ shifted(y2, shiftDrawCalls));
}
public void drawRect(int x, int y, int width, int height)
{
- draw(new Rectangle(x, y, width, height));
+ cairoDrawRect(nativePointer, shifted(x, shiftDrawCalls),
+ shifted(y, shiftDrawCalls), width, height);
}
public void fillArc(int x, int y, int width, int height, int startAngle,
@@ -865,7 +1006,7 @@ public abstract class CairoGraphics2D extends Graphics2D
public void fillRect(int x, int y, int width, int height)
{
- fill(new Rectangle(x, y, width, height));
+ cairoFillRect(nativePointer, x, y, width, height);
}
public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
@@ -972,19 +1113,19 @@ public abstract class CairoGraphics2D extends Graphics2D
|| hintKey.equals(RenderingHints.KEY_ALPHA_INTERPOLATION))
{
if (hintValue.equals(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
- cairoSurfaceSetFilter(0);
+ cairoSurfaceSetFilter(nativePointer, 0);
else if (hintValue.equals(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
- cairoSurfaceSetFilter(1);
+ cairoSurfaceSetFilter(nativePointer, 1);
else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED))
- cairoSurfaceSetFilter(2);
+ cairoSurfaceSetFilter(nativePointer, 2);
else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY))
- cairoSurfaceSetFilter(3);
+ cairoSurfaceSetFilter(nativePointer, 3);
else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT))
- cairoSurfaceSetFilter(4);
+ cairoSurfaceSetFilter(nativePointer, 4);
}
shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE)
@@ -1004,22 +1145,22 @@ public abstract class CairoGraphics2D extends Graphics2D
if (hints.containsKey(RenderingHints.KEY_INTERPOLATION))
{
if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
- cairoSurfaceSetFilter(0);
+ cairoSurfaceSetFilter(nativePointer, 0);
else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
- cairoSurfaceSetFilter(1);
+ cairoSurfaceSetFilter(nativePointer, 1);
}
if (hints.containsKey(RenderingHints.KEY_ALPHA_INTERPOLATION))
{
if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED))
- cairoSurfaceSetFilter(2);
+ cairoSurfaceSetFilter(nativePointer, 2);
else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY))
- cairoSurfaceSetFilter(3);
+ cairoSurfaceSetFilter(nativePointer, 3);
else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT))
- cairoSurfaceSetFilter(4);
+ cairoSurfaceSetFilter(nativePointer, 4);
}
shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE)
@@ -1051,7 +1192,7 @@ public abstract class CairoGraphics2D extends Graphics2D
// other way around. Therefore to get the "user -> pixel" transform
// that cairo wants from "image -> user" transform that we currently
// have, we will need to invert the transformation matrix.
- AffineTransform invertedXform = new AffineTransform();
+ AffineTransform invertedXform;
try
{
@@ -1063,11 +1204,18 @@ public abstract class CairoGraphics2D extends Graphics2D
+ xform.toString());
}
- // Unrecognized image - convert to a BufferedImage and come back.
+ // Unrecognized image - convert to a BufferedImage
+ // Note - this can get us in trouble when the gdk lock is re-acquired.
+ // for example by VolatileImage. See ComponentGraphics for how we work
+ // around this.
+
if( !(img instanceof BufferedImage) )
- return this.drawImage(Toolkit.getDefaultToolkit().
- createImage(img.getSource()),
- xform, bgcolor, obs);
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
BufferedImage b = (BufferedImage) img;
DataBuffer db;
@@ -1077,6 +1225,7 @@ public abstract class CairoGraphics2D extends Graphics2D
// If this BufferedImage has a BufferedImageGraphics object,
// use the cached CairoSurface that BIG is drawing onto
+
if( BufferedImageGraphics.bufferedImages.get( b ) != null )
db = (DataBuffer)BufferedImageGraphics.bufferedImages.get( b );
else
@@ -1084,9 +1233,14 @@ public abstract class CairoGraphics2D extends Graphics2D
invertedXform.getMatrix(i2u);
+ double alpha = 1.0;
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+
if(db instanceof CairoSurface)
{
- ((CairoSurface)db).drawSurface(this, i2u);
+ ((CairoSurface)db).drawSurface(nativePointer, i2u, alpha);
+ updateColor();
return true;
}
@@ -1103,26 +1257,9 @@ public abstract class CairoGraphics2D extends Graphics2D
setPaint( oldPaint );
}
- int[] pixels;
-
- // Shortcut for easy color models.
- if( b.getColorModel().equals(rgb32) )
- {
- pixels = ((DataBufferInt)db).getData();
- for(int i = 0; i < pixels.length; i++)
- pixels[i] |= 0xFF000000;
- }
- else if( b.getColorModel().equals(argb32) )
- {
- pixels = ((DataBufferInt)db).getData();
- }
- else
- {
- pixels = b.getRGB(0, 0, width, height,
- null, 0, width);
- }
+ int[] pixels = b.getRGB(0, 0, width, height, null, 0, width);
- drawPixels(pixels, width, height, width, i2u);
+ drawPixels(nativePointer, pixels, width, height, width, i2u, alpha);
// Cairo seems to lose the current color which must be restored.
updateColor();
@@ -1214,7 +1351,7 @@ public abstract class CairoGraphics2D extends Graphics2D
else
{ cy = dy2; ch = dy1 - dy2; }
- setClip( cx, cy, cw, ch );
+ clipRect( cx, cy, cw, ch );
AffineTransform tx = new AffineTransform();
tx.translate( dx1 - sx1*scaleX, dy1 - sy1*scaleY );
@@ -1238,8 +1375,8 @@ public abstract class CairoGraphics2D extends Graphics2D
{
if (str == null || str.length() == 0)
return;
-
- drawGlyphVector(getFont().createGlyphVector(null, str), x, y);
+ (new TextLayout( str, getFont(), getFontRenderContext() )).
+ draw(this, x, y);
}
public void drawString(String str, int x, int y)
@@ -1254,12 +1391,29 @@ public abstract class CairoGraphics2D extends Graphics2D
public void drawGlyphVector(GlyphVector gv, float x, float y)
{
- int n = gv.getNumGlyphs ();
- int[] codes = gv.getGlyphCodes (0, n, null);
- float[] positions = gv.getGlyphPositions (0, n, null);
-
- setFont (gv.getFont ());
- cairoDrawGlyphVector( (GdkFontPeer)getFont().getPeer(), x, y, n, codes, positions);
+ double alpha = 1.0;
+
+ if( gv.getNumGlyphs() <= 0 )
+ return;
+
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+ if (gv instanceof FreetypeGlyphVector && alpha == 1.0)
+ {
+ int n = gv.getNumGlyphs ();
+ int[] codes = gv.getGlyphCodes (0, n, null);
+ float[] positions = gv.getGlyphPositions (0, n, null);
+
+ setFont (gv.getFont ());
+ cairoDrawGlyphVector(nativePointer, (GdkFontPeer)getFont().getPeer(),
+ x, y, n, codes, positions);
+ }
+ else
+ {
+ translate(x, y);
+ fill(gv.getOutline());
+ translate(-x, -y);
+ }
}
public void drawString(AttributedCharacterIterator ci, float x, float y)
@@ -1412,7 +1566,11 @@ public abstract class CairoGraphics2D extends Graphics2D
for (int i = 0; i < pixels.length; i++)
pixels[i] |= 0xFF000000;
- drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u);
+ double alpha = 1.0;
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+ drawPixels(nativePointer, pixels, r.getWidth(), r.getHeight(),
+ r.getWidth(), i2u, alpha);
// Cairo seems to lose the current color which must be restored.
updateColor();
@@ -1440,7 +1598,7 @@ public abstract class CairoGraphics2D extends Graphics2D
double y = 0;
double[] coords = new double[6];
- cairoSetFillRule(p.getWindingRule());
+ cairoSetFillRule(nativePointer, p.getWindingRule());
for (; ! p.isDone(); p.next())
{
int seg = p.currentSegment(coords);
@@ -1449,12 +1607,12 @@ public abstract class CairoGraphics2D extends Graphics2D
case PathIterator.SEG_MOVETO:
x = shifted(coords[0], doShift);
y = shifted(coords[1], doShift);
- cairoMoveTo(x, y);
+ cairoMoveTo(nativePointer, x, y);
break;
case PathIterator.SEG_LINETO:
x = shifted(coords[0], doShift);
y = shifted(coords[1], doShift);
- cairoLineTo(x, y);
+ cairoLineTo(nativePointer, x, y);
break;
case PathIterator.SEG_QUADTO:
// splitting a quadratic bezier into a cubic:
@@ -1467,18 +1625,18 @@ public abstract class CairoGraphics2D extends Graphics2D
x = shifted(coords[2], doShift);
y = shifted(coords[3], doShift);
- cairoCurveTo(x1, y1, x2, y2, x, y);
+ cairoCurveTo(nativePointer, x1, y1, x2, y2, x, y);
break;
case PathIterator.SEG_CUBICTO:
x = shifted(coords[4], doShift);
y = shifted(coords[5], doShift);
- cairoCurveTo(shifted(coords[0], doShift),
+ cairoCurveTo(nativePointer, shifted(coords[0], doShift),
shifted(coords[1], doShift),
shifted(coords[2], doShift),
shifted(coords[3], doShift), x, y);
break;
case PathIterator.SEG_CLOSE:
- cairoClosePath();
+ cairoClosePath(nativePointer);
break;
}
}
@@ -1550,4 +1708,47 @@ public abstract class CairoGraphics2D extends Graphics2D
return db.getData();
}
+
+ /**
+ * Helper method to transform the clip. This is called by the various
+ * transformation-manipulation methods to update the clip (which is in
+ * userspace) accordingly.
+ *
+ * The transform usually is the inverse transform that was applied to the
+ * graphics object.
+ *
+ * @param t the transform to apply to the clip
+ */
+ private void updateClip(AffineTransform t)
+ {
+ if (clip == null)
+ return;
+
+ if (! (clip instanceof GeneralPath))
+ clip = new GeneralPath(clip);
+
+ GeneralPath p = (GeneralPath) clip;
+ p.transform(t);
+ }
+
+ private static Rectangle computeIntersection(int x, int y, int w, int h,
+ Rectangle rect)
+ {
+ int x2 = (int) rect.x;
+ int y2 = (int) rect.y;
+ int w2 = (int) rect.width;
+ int h2 = (int) rect.height;
+
+ int dx = (x > x2) ? x : x2;
+ int dy = (y > y2) ? y : y2;
+ int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx);
+ int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy);
+
+ if (dw >= 0 && dh >= 0)
+ rect.setBounds(dx, dy, dw, dh);
+ else
+ rect.setBounds(0, 0, 0, 0);
+
+ return rect;
+ }
}
diff --git a/gnu/java/awt/peer/gtk/CairoSurface.java b/gnu/java/awt/peer/gtk/CairoSurface.java
index c3b07d874..b4d08c6ad 100644
--- a/gnu/java/awt/peer/gtk/CairoSurface.java
+++ b/gnu/java/awt/peer/gtk/CairoSurface.java
@@ -52,6 +52,7 @@ import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.io.File;
import java.io.IOException;
+import java.nio.ByteOrder;
import java.util.Hashtable;
import java.util.Vector;
import java.io.ByteArrayOutputStream;
@@ -88,49 +89,65 @@ public class CairoSurface extends DataBuffer
/**
* Allocates and clears the buffer and creates the cairo surface.
* @param width, height - the image size
- * @param stride - the buffer row stride.
+ * @param stride - the buffer row stride. (in ints)
*/
private native void create(int width, int height, int stride);
/**
* Destroys the cairo surface and frees the buffer.
*/
- private native void destroy();
+ private native void destroy(long surfacePointer, long bufferPointer);
/**
* Gets buffer elements
*/
- private native int nativeGetElem(int i);
+ private native int nativeGetElem(long bufferPointer, int i);
/**
* Sets buffer elements.
*/
- private native void nativeSetElem(int i, int val);
+ private native void nativeSetElem(long bufferPointer, int i, int val);
/**
* Draws this image to a given CairoGraphics context,
* with an affine transform given by i2u.
*/
- public native void drawSurface(CairoGraphics2D context, double[] i2u);
+ public native void nativeDrawSurface(long surfacePointer, long contextPointer,
+ double[] i2u, double alpha);
+
+ public void drawSurface(long contextPointer, double[] i2u, double alpha)
+ {
+ nativeDrawSurface(surfacePointer, contextPointer, i2u, alpha);
+ }
/**
* getPixels -return the pixels as a java array.
*/
- native int[] getPixels(int size);
+ native int[] nativeGetPixels(long bufferPointer, int size);
+
+ public int[] getPixels(int size)
+ {
+ return nativeGetPixels(bufferPointer, size);
+ }
/**
* getPixels -return the pixels as a java array.
*/
- native void setPixels(int[] pixels);
+ native void nativeSetPixels(long bufferPointer, int[] pixels);
- native long getFlippedBuffer(int size);
+ public void setPixels(int[] pixels)
+ {
+ nativeSetPixels(bufferPointer, pixels);
+ }
+
+ native long getFlippedBuffer(long bufferPointer, int size);
/**
* Create a cairo_surface_t with specified width and height.
* The format will be ARGB32 with premultiplied alpha and native bit
* and word ordering.
*/
- CairoSurface(int width, int height)
+ public CairoSurface(int width, int height)
{
super(DataBuffer.TYPE_INT, width * height);
@@ -140,7 +157,7 @@ public class CairoSurface extends DataBuffer
this.width = width;
this.height = height;
- create(width, height, width * 4);
+ create(width, height, width);
if(surfacePointer == 0 || bufferPointer == 0)
throw new Error("Could not allocate bitmap.");
@@ -160,29 +177,52 @@ public class CairoSurface extends DataBuffer
width = image.width;
height = image.height;
- create(width, height, width * 4);
-
+ create(width, height, width);
+
if(surfacePointer == 0 || bufferPointer == 0)
throw new Error("Could not allocate bitmap.");
-
+
// Copy the pixel data from the GtkImage.
int[] data = image.getPixels();
// Swap ordering from GdkPixbuf to Cairo
for(int i = 0; i < data.length; i++ )
{
- int alpha = (data[i] & 0xFF000000) >> 24;
- if( alpha == 0 ) // I do not know why we need this, but it works.
- data[i] = 0;
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+ {
+ // On a big endian system we get a RRGGBBAA data array.
+ int alpha = (data[i] & 0xFF);
+ if( alpha == 0 ) // I do not know why we need this, but it works.
+ data[i] = 0;
+ else
+ {
+ int r = (((data[i] & 0xFF000000) >> 24));
+ int g = (((data[i] & 0x00FF0000) >> 16));
+ int b = (((data[i] & 0x0000FF00) >> 8));
+ // Cairo needs a ARGB32 native array.
+ data[i] = (( alpha << 24 ) & 0xFF000000)
+ | (( r << 16 ) & 0x00FF0000)
+ | (( g << 8 ) & 0x0000FF00)
+ | ( b & 0x000000FF);
+ }
+ }
else
{
- int r = (((data[i] & 0x00FF0000) >> 16) );
- int g = (((data[i] & 0x0000FF00) >> 8) );
- int b = ((data[i] & 0x000000FF) );
- data[i] = (( alpha << 24 ) & 0xFF000000)
- | (( b << 16 ) & 0x00FF0000)
- | (( g << 8 ) & 0x0000FF00)
- | ( r & 0x000000FF);
+ // On a little endian system we get a AABBGGRR data array.
+ int alpha = (data[i] & 0xFF000000) >> 24;
+ if( alpha == 0 ) // I do not know why we need this, but it works.
+ data[i] = 0;
+ else
+ {
+ int b = (((data[i] & 0x00FF0000) >> 16));
+ int g = (((data[i] & 0x0000FF00) >> 8));
+ int r = ((data[i] & 0x000000FF));
+ // Cairo needs a ARGB32 native array.
+ data[i] = (( alpha << 24 ) & 0xFF000000)
+ | (( r << 16 ) & 0x00FF0000)
+ | (( g << 8 ) & 0x0000FF00)
+ | ( b & 0x000000FF);
+ }
}
}
@@ -195,7 +235,15 @@ public class CairoSurface extends DataBuffer
public void dispose()
{
if(surfacePointer != 0)
- destroy();
+ destroy(surfacePointer, bufferPointer);
+ }
+
+ /**
+ * Call dispose() to clean up any native resources allocated.
+ */
+ protected void finalize()
+ {
+ dispose();
}
/**
@@ -203,7 +251,8 @@ public class CairoSurface extends DataBuffer
*/
public GtkImage getGtkImage()
{
- return new GtkImage( width, height, getFlippedBuffer( width * height ));
+ return new GtkImage( width, height,
+ getFlippedBuffer(bufferPointer, width * height ));
}
/**
@@ -243,7 +292,7 @@ public class CairoSurface extends DataBuffer
{
if(bank != 0 || i < 0 || i >= width*height)
throw new IndexOutOfBoundsException(i+" size: "+width*height);
- return nativeGetElem(i);
+ return nativeGetElem(bufferPointer, i);
}
/**
@@ -253,7 +302,7 @@ public class CairoSurface extends DataBuffer
{
if(bank != 0 || i < 0 || i >= width*height)
throw new IndexOutOfBoundsException(i+" size: "+width*height);
- nativeSetElem(i, val);
+ nativeSetElem(bufferPointer, i, val);
}
/**
@@ -269,12 +318,22 @@ public class CairoSurface extends DataBuffer
* Creates a cairo_t drawing context, returns the pointer as a long.
* Used by CairoSurfaceGraphics.
*/
- native long newCairoContext();
+ native long nativeNewCairoContext(long surfacePointer);
+
+ public long newCairoContext()
+ {
+ return nativeNewCairoContext(surfacePointer);
+ }
/**
* Copy an area of the surface. Expects parameters must be within bounds.
* Count on a segfault otherwise.
*/
- native void copyAreaNative(int x, int y, int width, int height,
- int dx, int dy, int stride);
+ native void copyAreaNative2(long bufferPointer, int x, int y, int width,
+ int height, int dx, int dy, int stride);
+ public void copyAreaNative(int x, int y, int width,
+ int height, int dx, int dy, int stride)
+ {
+ copyAreaNative2(bufferPointer, x, y, width, height, dx, dy, stride);
+ }
}
diff --git a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
index 38c549d1d..91f0b4981 100644
--- a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
+++ b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
@@ -40,6 +40,7 @@ package gnu.java.awt.peer.gtk;
import java.awt.Graphics;
import java.awt.Color;
+import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.Graphics2D;
@@ -63,7 +64,6 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
this.surface = surface;
cairo_t = surface.newCairoContext();
setup( cairo_t );
- setClip(0, 0, surface.width, surface.height);
}
/**
@@ -75,7 +75,6 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
surface = copyFrom.surface;
cairo_t = surface.newCairoContext();
copy( copyFrom, cairo_t );
- setClip(0, 0, surface.width, surface.height);
}
public Graphics create()
@@ -85,7 +84,7 @@ public class CairoSurfaceGraphics extends CairoGraphics2D
public GraphicsConfiguration getDeviceConfiguration()
{
- throw new UnsupportedOperationException();
+ return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
protected Rectangle2D getRealBounds()
diff --git a/gnu/java/awt/peer/gtk/ComponentGraphics.java b/gnu/java/awt/peer/gtk/ComponentGraphics.java
index 5f17d7bef..cb8350265 100644
--- a/gnu/java/awt/peer/gtk/ComponentGraphics.java
+++ b/gnu/java/awt/peer/gtk/ComponentGraphics.java
@@ -39,20 +39,19 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Color;
-import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
-import java.awt.font.FontRenderContext;
+import java.awt.Toolkit;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
-import java.awt.image.ImagingOpException;
+import java.awt.image.ImageProducer;
import java.awt.image.RenderedImage;
/**
@@ -64,8 +63,41 @@ import java.awt.image.RenderedImage;
public class ComponentGraphics extends CairoGraphics2D
{
private GtkComponentPeer component;
- private long cairo_t;
+ protected long cairo_t;
+ private static ThreadLocal hasLock = new ThreadLocal();
+ private static Integer ONE = Integer.valueOf(1);
+
+ private void lock()
+ {
+ Integer i = (Integer) hasLock.get();
+ if (i == null)
+ {
+ start_gdk_drawing();
+ hasLock.set(ONE);
+ }
+ else
+ hasLock.set(Integer.valueOf(i.intValue() + 1));
+ }
+
+ private void unlock()
+ {
+ Integer i = (Integer) hasLock.get();
+ if (i == null)
+ throw new IllegalStateException();
+ if (i == ONE)
+ {
+ hasLock.set(null);
+ end_gdk_drawing();
+ }
+ else
+ hasLock.set(Integer.valueOf(i.intValue() - 1));
+ }
+
+ ComponentGraphics()
+ {
+ }
+
private ComponentGraphics(GtkComponentPeer component)
{
this.component = component;
@@ -94,6 +126,26 @@ public class ComponentGraphics extends CairoGraphics2D
private native long initState(GtkComponentPeer component);
/**
+ * Destroys the component surface and calls dispose on the cairo
+ * graphics2d to destroy any super class resources.
+ */
+ public void dispose()
+ {
+ super.dispose();
+ disposeSurface(nativePointer);
+ }
+
+ /**
+ * Destroys the component surface.
+ */
+ private native void disposeSurface(long nativePointer);
+
+ /**
+ * Creates a cairo_t for a volatile image
+ */
+ protected native long initFromVolatile( long pixmapPtr, int width, int height);
+
+ /**
* Grab lock
*/
private native void start_gdk_drawing();
@@ -113,8 +165,9 @@ public class ComponentGraphics extends CairoGraphics2D
int width, int height, int dx, int dy);
private native void drawVolatile(GtkComponentPeer component,
- Image vimg, int x, int y,
- int width, int height);
+ long vimg, int x, int y,
+ int width, int height, int cx, int cy,
+ int cw, int ch);
/**
* Returns a Graphics2D object for a component, either an instance of this
@@ -155,65 +208,198 @@ public class ComponentGraphics extends CairoGraphics2D
*/
public void draw(Shape s)
{
- start_gdk_drawing();
- super.draw(s);
- end_gdk_drawing();
+ lock();
+ try
+ {
+ super.draw(s);
+ }
+ finally
+ {
+ unlock();
+ }
}
public void fill(Shape s)
{
- start_gdk_drawing();
- super.fill(s);
- end_gdk_drawing();
+ lock();
+ try
+ {
+ super.fill(s);
+ }
+ finally
+ {
+ unlock();
+ }
}
public void drawRenderedImage(RenderedImage image, AffineTransform xform)
{
- start_gdk_drawing();
- super.drawRenderedImage(image, xform);
- end_gdk_drawing();
+ lock();
+ try
+ {
+ super.drawRenderedImage(image, xform);
+ }
+ finally
+ {
+ unlock();
+ }
}
protected boolean drawImage(Image img, AffineTransform xform,
Color bgcolor, ImageObserver obs)
{
- start_gdk_drawing();
- boolean rv = super.drawImage(img, xform, bgcolor, obs);
- end_gdk_drawing();
+ boolean rv;
+ lock();
+ try
+ {
+ rv = super.drawImage(img, xform, bgcolor, obs);
+ }
+ finally
+ {
+ unlock();
+ }
return rv;
}
public void drawGlyphVector(GlyphVector gv, float x, float y)
{
- start_gdk_drawing();
- super.drawGlyphVector(gv, x, y);
- end_gdk_drawing();
+ lock();
+ try
+ {
+ super.drawGlyphVector(gv, x, y);
+ }
+ finally
+ {
+ unlock();
+ }
}
public boolean drawImage(Image img, int x, int y, ImageObserver observer)
{
- if( img instanceof GtkVolatileImage )
+ // If it is a GtkVolatileImage with an "easy" transform then
+ // draw directly. Always pass a BufferedImage to super to avoid
+ // deadlock (see Note in CairoGraphics.drawImage()).
+ if (img instanceof GtkVolatileImage)
{
- ((GtkVolatileImage)img).validate( null );
- drawVolatile( component, img, x, y-20 ,
- ((GtkVolatileImage)img).width,
- ((GtkVolatileImage)img).height );
- return true;
- }
- return super.drawImage( img, x, y, observer );
+ GtkVolatileImage vimg = (GtkVolatileImage) img;
+ int type = transform.getType();
+ if ((type == AffineTransform.TYPE_IDENTITY
+ || type == AffineTransform.TYPE_TRANSLATION)
+ && (clip == null || clip instanceof Rectangle2D))
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ if (r == null)
+ r = getRealBounds();
+ x += transform.getTranslateX();
+ y += transform.getTranslateY();
+ drawVolatile(component, vimg.nativePointer,
+ x, y, vimg.width, vimg.height,
+ (int) (r.getX() + transform.getTranslateX()),
+ (int) (r.getY() + transform.getTranslateY()),
+ (int) r.getWidth(),
+ (int) r.getHeight());
+ return true;
+ }
+ else
+ return super.drawImage(vimg.getSnapshot(), x, y, observer);
+ }
+
+ BufferedImage bimg;
+ if (img instanceof BufferedImage)
+ bimg = (BufferedImage) img;
+ else
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
+ }
+ return super.drawImage(bimg, x, y, observer);
}
public boolean drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer)
{
- if( img instanceof GtkVolatileImage )
+ // If it is a GtkVolatileImage with an "easy" transform then
+ // draw directly. Always pass a BufferedImage to super to avoid
+ // deadlock (see Note in CairoGraphics.drawImage()).
+ if (img instanceof GtkVolatileImage
+ && (clip == null || clip instanceof Rectangle2D))
+ {
+ GtkVolatileImage vimg = (GtkVolatileImage) img;
+ int type = transform.getType();
+ if ((type == AffineTransform.TYPE_IDENTITY
+ || type == AffineTransform.TYPE_TRANSLATION)
+ && (clip == null || clip instanceof Rectangle2D))
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ if (r == null)
+ r = getRealBounds();
+ x += transform.getTranslateX();
+ y += transform.getTranslateY();
+ drawVolatile(component, vimg.nativePointer,
+ x, y, width, height,
+ (int) (r.getX() + transform.getTranslateX()),
+ (int) (r.getY() + transform.getTranslateY()),
+ (int) r.getWidth(),
+ (int) r.getHeight());
+ return true;
+ }
+ else
+ return super.drawImage(vimg.getSnapshot(), x, y,
+ width, height, observer);
+ }
+
+ BufferedImage bimg;
+ if (img instanceof BufferedImage)
+ bimg = (BufferedImage) img;
+ else
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
+ }
+ return super.drawImage(bimg, x, y, width, height, observer);
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ lock();
+ try
+ {
+ super.drawLine(x1, y1, x2, y2);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ public void drawRect(int x, int y, int width, int height)
+ {
+ lock();
+ try
+ {
+ super.drawRect(x, y, width, height);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ public void fillRect(int x, int y, int width, int height)
+ {
+ lock();
+ try
+ {
+ super.fillRect(x, y, width, height);
+ }
+ finally
{
- ((GtkVolatileImage)img).validate( null );
- drawVolatile( component, img, x, y-20,
- width, height );
- return true;
- }
- return super.drawImage( img, x, y, width, height, observer );
+ unlock();
+ }
}
}
diff --git a/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
new file mode 100644
index 000000000..2c9d91793
--- /dev/null
+++ b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
@@ -0,0 +1,504 @@
+/* FreetypeGlyphVector.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Font;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.GeneralPath;
+import java.awt.font.GlyphJustificationInfo;
+import java.awt.font.GlyphMetrics;
+import java.awt.font.GlyphVector;
+import java.awt.font.FontRenderContext;
+
+public class FreetypeGlyphVector extends GlyphVector
+{
+ /**
+ * The associated font and its peer.
+ */
+ private Font font;
+ private GdkFontPeer peer; // ATTN: Accessed from native code.
+
+ private Rectangle2D logicalBounds;
+
+ private float[] glyphPositions;
+ /**
+ * The string represented by this GlyphVector.
+ */
+ private String s;
+
+ /**
+ * The font render context
+ */
+ private FontRenderContext frc;
+
+ /**
+ * The total # of glyphs.
+ */
+ private int nGlyphs;
+
+ /**
+ * The glyph codes
+ */
+ private int[] glyphCodes;
+
+ /**
+ * Glyph transforms. (de facto only the translation is used)
+ */
+ private AffineTransform[] glyphTransforms;
+
+ private GlyphMetrics[] metricsCache;
+
+ /**
+ * Create a glyphvector from a given (Freetype) font and a String.
+ */
+ public FreetypeGlyphVector(Font f, String s, FontRenderContext frc)
+ {
+ this(f, s, frc, Font.LAYOUT_LEFT_TO_RIGHT);
+ }
+
+ /**
+ * Create a glyphvector from a given (Freetype) font and a String.
+ */
+ public FreetypeGlyphVector(Font f, String s, FontRenderContext frc,
+ int flags)
+ {
+ this.s = s;
+ this.font = f;
+ this.frc = frc;
+ if( !(font.getPeer() instanceof GdkFontPeer ) )
+ throw new IllegalArgumentException("Not a valid font.");
+ peer = (GdkFontPeer)font.getPeer();
+
+ getGlyphs();
+ if( flags == Font.LAYOUT_RIGHT_TO_LEFT )
+ {
+ // reverse the glyph ordering.
+ int[] temp = new int[ nGlyphs ];
+ for(int i = 0; i < nGlyphs; i++)
+ temp[ i ] = glyphCodes[ nGlyphs - i - 1];
+ glyphCodes = temp;
+ }
+ performDefaultLayout();
+ }
+
+ /**
+ * Create a glyphvector from a given set of glyph codes.
+ */
+ public FreetypeGlyphVector(Font f, int[] codes, FontRenderContext frc)
+ {
+ this.font = f;
+ this.frc = frc;
+ if( !(font.getPeer() instanceof GdkFontPeer ) )
+ throw new IllegalArgumentException("Not a valid font.");
+ peer = (GdkFontPeer)font.getPeer();
+
+ glyphCodes = new int[ codes.length ];
+ System.arraycopy(codes, 0, glyphCodes, 0, codes.length);
+ nGlyphs = glyphCodes.length;
+ performDefaultLayout();
+ }
+
+ /**
+ * Cloning constructor
+ */
+ private FreetypeGlyphVector( FreetypeGlyphVector gv )
+ {
+ font = gv.font;
+ peer = gv.peer;
+ frc = gv.frc;
+ s = gv.s;
+ nGlyphs = gv.nGlyphs;
+ logicalBounds = gv.logicalBounds.getBounds2D();
+
+ if( gv.metricsCache != null )
+ {
+ metricsCache = new GlyphMetrics[ nGlyphs ];
+ System.arraycopy(gv.metricsCache, 0, metricsCache, 0, nGlyphs);
+ }
+
+ glyphCodes = new int[ nGlyphs ];
+ glyphPositions = new float[ nGlyphs ];
+ glyphTransforms = new AffineTransform[ nGlyphs ];
+ for(int i = 0; i < nGlyphs; i++ )
+ {
+ glyphTransforms[ i ] = new AffineTransform( gv.glyphTransforms[ i ] );
+ glyphCodes[i] = gv.glyphCodes[ i ];
+ glyphPositions[i] = gv.glyphPositions[ i ];
+ }
+ }
+
+ /**
+ * Create the array of glyph codes.
+ */
+ private void getGlyphs()
+ {
+ nGlyphs = s.codePointCount( 0, s.length() );
+ glyphCodes = new int[ nGlyphs ];
+ int[] codePoints = new int[ nGlyphs ];
+ int stringIndex = 0;
+
+ for(int i = 0; i < nGlyphs; i++)
+ {
+ codePoints[i] = s.codePointAt( stringIndex );
+ // UTF32 surrogate handling
+ if( codePoints[i] != (int)s.charAt( stringIndex ) )
+ stringIndex ++;
+ stringIndex ++;
+ }
+
+ glyphCodes = getGlyphs( codePoints );
+ }
+
+ /**
+ * Returns the glyph code within the font for a given character
+ */
+ public native int[] getGlyphs(int[] codepoints);
+
+ /**
+ * Returns the kerning of a glyph pair
+ */
+ private native Point2D getKerning(int leftGlyph, int rightGlyph);
+
+ private native double[] getMetricsNative( int glyphCode );
+
+ private native GeneralPath getGlyphOutlineNative(int glyphIndex);
+
+
+ public Object clone()
+ {
+ return new FreetypeGlyphVector( this );
+ }
+
+ /**
+ * Duh, compares two instances.
+ */
+ public boolean equals(GlyphVector gv)
+ {
+ if( ! (gv instanceof FreetypeGlyphVector) )
+ return false;
+
+ return (((FreetypeGlyphVector)gv).font.equals(font) &&
+ ((FreetypeGlyphVector)gv).frc.equals(frc)
+ && ((FreetypeGlyphVector)gv).s.equals(s));
+ }
+
+ /**
+ * Returns the associated Font
+ */
+ public Font getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Returns the associated FontRenderContext
+ */
+ public FontRenderContext getFontRenderContext()
+ {
+ return frc;
+ }
+
+ /**
+ * Layout the glyphs.
+ */
+ public void performDefaultLayout()
+ {
+ logicalBounds = null; // invalidate caches.
+ glyphPositions = null;
+
+ glyphTransforms = new AffineTransform[ nGlyphs ];
+ double x = 0;
+
+ for(int i = 0; i < nGlyphs; i++)
+ {
+ GlyphMetrics gm = getGlyphMetrics( i );
+ glyphTransforms[ i ] = AffineTransform.getTranslateInstance(x, 0);
+ x += gm.getAdvanceX();
+ if( i > 0 )
+ {
+ Point2D p = getKerning( glyphCodes[ i - 1 ], glyphCodes[ i ] );
+ x += p.getX();
+ }
+ }
+ }
+
+ /**
+ * Returns the code of the glyph at glyphIndex;
+ */
+ public int getGlyphCode(int glyphIndex)
+ {
+ return glyphCodes[ glyphIndex ];
+ }
+
+ /**
+ * Returns multiple glyphcodes.
+ */
+ public int[] getGlyphCodes(int beginGlyphIndex, int numEntries,
+ int[] codeReturn)
+ {
+ int[] rval;
+
+ if( codeReturn == null )
+ rval = new int[ numEntries ];
+ else
+ rval = codeReturn;
+
+ System.arraycopy(glyphCodes, beginGlyphIndex, rval, 0, numEntries);
+
+ return rval;
+ }
+
+ /**
+ * FIXME: Implement me.
+ */
+ public Shape getGlyphLogicalBounds(int glyphIndex)
+ {
+ GlyphMetrics gm = getGlyphMetrics( glyphIndex );
+ if( gm == null )
+ return null;
+ Rectangle2D r = gm.getBounds2D();
+ Point2D p = getGlyphPosition( glyphIndex );
+ return new Rectangle2D.Double( p.getX() + r.getX() - gm.getLSB(),
+ p.getY() + r.getY(),
+ gm.getAdvanceX(),
+ r.getHeight() );
+ }
+
+ /*
+ * FIXME: Not all glyph types are supported.
+ * (The JDK doesn't really seem to do so either)
+ */
+ public void setupGlyphMetrics()
+ {
+ metricsCache = new GlyphMetrics[ nGlyphs ];
+
+ for(int i = 0; i < nGlyphs; i++)
+ {
+ GlyphMetrics gm = (GlyphMetrics)
+ peer.getGlyphMetrics( glyphCodes[ i ] );
+ if( gm == null )
+ {
+ double[] val = getMetricsNative( glyphCodes[ i ] );
+ if( val == null )
+ gm = null;
+ else
+ {
+ gm = new GlyphMetrics( true,
+ (float)val[1],
+ (float)val[2],
+ new Rectangle2D.Double
+ ( val[3], val[4],
+ val[5], val[6] ),
+ GlyphMetrics.STANDARD );
+ peer.putGlyphMetrics( glyphCodes[ i ], gm );
+ }
+ }
+ metricsCache[ i ] = gm;
+ }
+ }
+
+ /**
+ * Returns the metrics of a single glyph.
+ */
+ public GlyphMetrics getGlyphMetrics(int glyphIndex)
+ {
+ if( metricsCache == null )
+ setupGlyphMetrics();
+
+ return metricsCache[ glyphIndex ];
+ }
+
+ /**
+ * Returns the outline of a single glyph.
+ */
+ public Shape getGlyphOutline(int glyphIndex)
+ {
+ GeneralPath gp = getGlyphOutlineNative( glyphCodes[ glyphIndex ] );
+ gp.transform( glyphTransforms[ glyphIndex ] );
+ return gp;
+ }
+
+ /**
+ * Returns the position of a single glyph.
+ */
+ public Point2D getGlyphPosition(int glyphIndex)
+ {
+ return glyphTransforms[ glyphIndex ].transform( new Point2D.Double(0, 0),
+ null );
+ }
+
+ /**
+ * Returns the positions of multiple glyphs.
+ */
+ public float[] getGlyphPositions(int beginGlyphIndex, int numEntries,
+ float[] positionReturn)
+ {
+ if( glyphPositions != null )
+ return glyphPositions;
+
+ float[] rval;
+
+ if( positionReturn == null )
+ rval = new float[2 * numEntries];
+ else
+ rval = positionReturn;
+
+ for( int i = beginGlyphIndex; i < numEntries; i++ )
+ {
+ Point2D p = getGlyphPosition( i );
+ rval[i * 2] = (float)p.getX();
+ rval[i * 2 + 1] = (float)p.getY();
+ }
+
+ glyphPositions = rval;
+ return rval;
+ }
+
+ /**
+ * Returns the transform of a glyph.
+ */
+ public AffineTransform getGlyphTransform(int glyphIndex)
+ {
+ return new AffineTransform( glyphTransforms[ glyphIndex ] );
+ }
+
+ /**
+ * Returns the visual bounds of a glyph
+ * May be off by a pixel or two due to hinting/rasterization.
+ */
+ public Shape getGlyphVisualBounds(int glyphIndex)
+ {
+ return getGlyphOutline( glyphIndex ).getBounds2D();
+ }
+
+ /**
+ * Return the logical bounds of the whole thing.
+ */
+ public Rectangle2D getLogicalBounds()
+ {
+ if( nGlyphs == 0 )
+ return new Rectangle2D.Double(0, 0, 0, 0);
+ if( logicalBounds != null )
+ return logicalBounds;
+
+ Rectangle2D rect = (Rectangle2D)getGlyphLogicalBounds( 0 );
+ for( int i = 1; i < nGlyphs; i++ )
+ {
+ Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i );
+ rect = rect.createUnion( r2 );
+ }
+
+ logicalBounds = rect;
+ return rect;
+ }
+
+ /**
+ * Returns the number of glyphs.
+ */
+ public int getNumGlyphs()
+ {
+ return glyphCodes.length;
+ }
+
+ /**
+ * Returns the outline of the entire GlyphVector.
+ */
+ public Shape getOutline()
+ {
+ GeneralPath path = new GeneralPath();
+ for( int i = 0; i < getNumGlyphs(); i++ )
+ path.append( getGlyphOutline( i ), false );
+ return path;
+ }
+
+ /**
+ * TODO:
+ * FreeType does not currently have an API for the JSTF table. We should
+ * probably get the table ourselves from FT and pass it to some parser
+ * which the native font peers will need.
+ */
+ public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the outline of the entire vector, drawn at (x,y).
+ */
+ public Shape getOutline(float x, float y)
+ {
+ AffineTransform tx = AffineTransform.getTranslateInstance( x, y );
+ GeneralPath gp = (GeneralPath)getOutline();
+ gp.transform( tx );
+ return gp;
+ }
+
+ /**
+ * Returns the visual bounds of the entire GlyphVector.
+ * May be off by a pixel or two due to hinting/rasterization.
+ */
+ public Rectangle2D getVisualBounds()
+ {
+ return getOutline().getBounds2D();
+ }
+
+ /**
+ * Sets the position of a glyph.
+ */
+ public void setGlyphPosition(int glyphIndex, Point2D newPos)
+ {
+ // FIXME: Scaling, etc.?
+ glyphTransforms[ glyphIndex ].setToTranslation( newPos.getX(),
+ newPos.getY() );
+ logicalBounds = null;
+ glyphPositions = null;
+ }
+
+ /**
+ * Sets the transform of a single glyph.
+ */
+ public void setGlyphTransform(int glyphIndex, AffineTransform newTX)
+ {
+ glyphTransforms[ glyphIndex ].setTransform( newTX );
+ logicalBounds = null;
+ glyphPositions = null;
+ }
+}
diff --git a/gnu/java/awt/peer/gtk/GdkFontPeer.java b/gnu/java/awt/peer/gtk/GdkFontPeer.java
index 4781cb067..f5ed8a710 100644
--- a/gnu/java/awt/peer/gtk/GdkFontPeer.java
+++ b/gnu/java/awt/peer/gtk/GdkFontPeer.java
@@ -47,20 +47,28 @@ import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
+import java.awt.font.GlyphMetrics;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.nio.ByteBuffer;
+import java.util.HashMap;
public class GdkFontPeer extends ClasspathFontPeer
{
static native void initStaticState();
private final int native_state = GtkGenericPeer.getUniqueInteger ();
private static ResourceBundle bundle;
+
+ /**
+ * Cache GlyphMetrics objects.
+ */
+ private HashMap metricsCache;
static
{
@@ -143,6 +151,7 @@ public class GdkFontPeer extends ClasspathFontPeer
super(name, style, size);
initState ();
setFont (this.familyName, this.style, (int)this.size);
+ metricsCache = new HashMap();
}
public GdkFontPeer (String name, Map attributes)
@@ -150,6 +159,7 @@ public class GdkFontPeer extends ClasspathFontPeer
super(name, attributes);
initState ();
setFont (this.familyName, this.style, (int)this.size);
+ metricsCache = new HashMap();
}
/**
@@ -234,39 +244,41 @@ public class GdkFontPeer extends ClasspathFontPeer
return -1;
}
- private native GdkGlyphVector getGlyphVector(String txt,
- Font f,
- FontRenderContext ctx);
-
public GlyphVector createGlyphVector (Font font,
FontRenderContext ctx,
CharacterIterator i)
{
- return getGlyphVector(buildString (i), font, ctx);
+ return new FreetypeGlyphVector(font, buildString (i), ctx);
}
public GlyphVector createGlyphVector (Font font,
FontRenderContext ctx,
int[] glyphCodes)
{
- return null;
- // return new GdkGlyphVector (font, this, ctx, glyphCodes);
+ return new FreetypeGlyphVector(font, glyphCodes, ctx);
}
public byte getBaselineFor (Font font, char c)
{
- throw new UnsupportedOperationException ();
+ // FIXME: Actually check.
+ return Font.ROMAN_BASELINE;
}
- protected class GdkFontLineMetrics extends LineMetrics
+ private static class GdkFontLineMetrics extends LineMetrics
{
- FontMetrics fm;
- int nchars;
+ private FontMetrics fm;
+ private int nchars;
+ private float strikethroughOffset, strikethroughThickness,
+ underlineOffset, underlineThickness;
- public GdkFontLineMetrics (FontMetrics m, int n)
+ public GdkFontLineMetrics (GdkFontPeer fp, FontMetrics m, int n)
{
fm = m;
nchars = n;
+ strikethroughOffset = 0f;
+ underlineOffset = 0f;
+ strikethroughThickness = ((float)fp.getSize(null)) / 12f;
+ underlineThickness = strikethroughThickness;
}
public float getAscent()
@@ -275,7 +287,8 @@ public class GdkFontPeer extends ClasspathFontPeer
}
public int getBaselineIndex()
- {
+ {
+ // FIXME
return Font.ROMAN_BASELINE;
}
@@ -306,7 +319,7 @@ public class GdkFontPeer extends ClasspathFontPeer
public LineMetrics getLineMetrics (Font font, CharacterIterator ci,
int begin, int limit, FontRenderContext rc)
{
- return new GdkFontLineMetrics (getFontMetrics (font), limit - begin);
+ return new GdkFontLineMetrics (this, getFontMetrics (font), limit - begin);
}
public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
@@ -338,7 +351,9 @@ public class GdkFontPeer extends ClasspathFontPeer
public Rectangle2D getStringBounds (Font font, CharacterIterator ci,
int begin, int limit, FontRenderContext frc)
{
- GdkGlyphVector gv = getGlyphVector(buildString (ci, begin, limit), font, frc);
+ GlyphVector gv = new FreetypeGlyphVector( font,
+ buildString(ci, begin, limit),
+ frc);
return gv.getVisualBounds();
}
@@ -351,20 +366,15 @@ public class GdkFontPeer extends ClasspathFontPeer
char[] chars, int start, int limit,
int flags)
{
- int nchars = (limit - start) + 1;
- char[] nc = new char[nchars];
-
- for (int i = 0; i < nchars; ++i)
- nc[i] = chars[start + i];
-
- return createGlyphVector (font, frc,
- new StringCharacterIterator (new String (nc)));
+ return new FreetypeGlyphVector( font, new String( chars, start,
+ limit - start),
+ frc, flags);
}
public LineMetrics getLineMetrics (Font font, String str,
FontRenderContext frc)
{
- return new GdkFontLineMetrics (getFontMetrics (font), str.length ());
+ return new GdkFontLineMetrics (this, getFontMetrics (font), str.length ());
}
public FontMetrics getFontMetrics (Font font)
@@ -374,4 +384,20 @@ public class GdkFontPeer extends ClasspathFontPeer
return Toolkit.getDefaultToolkit().getFontMetrics (font);
}
+ /**
+ * Returns a cached GlyphMetrics object for a given glyphcode,
+ * or null if it doesn't exist in the cache.
+ */
+ GlyphMetrics getGlyphMetrics( int glyphCode )
+ {
+ return (GlyphMetrics)metricsCache.get( new Integer( glyphCode ) );
+ }
+
+ /**
+ * Put a GlyphMetrics object in the cache.
+ */
+ void putGlyphMetrics( int glyphCode, Object metrics )
+ {
+ metricsCache.put( new Integer( glyphCode ), metrics );
+ }
}
diff --git a/gnu/java/awt/peer/gtk/GdkGlyphVector.java b/gnu/java/awt/peer/gtk/GdkGlyphVector.java
deleted file mode 100644
index f0ddea43a..000000000
--- a/gnu/java/awt/peer/gtk/GdkGlyphVector.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/* GdkGlyphVector.java -- Glyph vector object
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.java.awt.peer.gtk;
-
-import java.awt.Font;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphJustificationInfo;
-import java.awt.font.GlyphMetrics;
-import java.awt.font.GlyphVector;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-
-public class GdkGlyphVector extends GlyphVector
-{
-
- /* We use a simple representation for glyph vectors here. Glyph i
- * consumes 8 doubles:
- *
- * logical x: extents[ 10*i ]
- * logical y: extents[ 10*i + 1 ]
- * logical width: extents[ 10*i + 2 ]
- * logical height: extents[ 10*i + 3 ]
- *
- * visual x: extents[ 10*i + 4 ]
- * visual y: extents[ 10*i + 5 ]
- * visual width: extents[ 10*i + 6 ]
- * visual height: extents[ 10*i + 7 ]
- *
- * origin pos x: extents[ 10*i + 8 ]
- * origin pos y: extents[ 10*i + 9 ]
- *
- * as well as one int, code[i], representing the glyph code in the font.
- */
-
- double [] extents;
- int [] codes;
-
- Font font;
- FontRenderContext fontRenderContext;
-
- Rectangle2D allLogical;
- Rectangle2D allVisual;
-
- public GdkGlyphVector(double[] extents, int[] codes, Font font, FontRenderContext frc)
- {
- this.extents = extents;
- this.codes = codes;
- this.font = font;
- this.fontRenderContext = frc;
-
- allLogical = new Rectangle2D.Double();
- allVisual = new Rectangle2D.Double();
-
- for (int i = 0; i < codes.length; ++i)
- {
- allLogical.add (new Rectangle2D.Double(extents[10*i ] + extents[10*i + 8],
- extents[10*i + 1] + extents[10*i + 9],
- extents[10*i + 2],
- extents[10*i + 3]));
-
- allVisual.add (new Rectangle2D.Double(extents[10*i + 4] + extents[10*i + 8],
- extents[10*i + 5] + extents[10*i + 9],
- extents[10*i + 6],
- extents[10*i + 7]));
- }
- }
-
- /*
- geometric notes:
-
- the FRC contains a mapping from points -> pixels.
-
- typographics points are typically 1/72 of an inch.
-
- pixel displays are often around 72 dpi.
-
- so the FRC can get away with using an identity transform on a screen,
- often. behavior is documented by sun to fall back to an identity
- transform if the internal transformation is null.
-
- coordinates coming up from pango are expressed as floats -- in device
- space, so basically pixels-with-fractional-bits -- derived from their
- storage format in pango (1024ths of pixels).
-
- it is not clear from the javadocs whether the results of methods like
- getGlyphPositions ought to return coordinates in device space, or
- "point" space, or what. for now I'm returning them in device space.
-
- */
-
- public double[] getExtents()
- {
- return extents;
- }
-
- public int[] getCodes()
- {
- return codes;
- }
-
- public Font getFont ()
- {
- return font;
- }
-
- public FontRenderContext getFontRenderContext ()
- {
- return fontRenderContext;
- }
-
- public int getGlyphCharIndex (int glyphIndex)
- {
- // FIXME: currently pango does not provide glyph-by-glyph
- // reverse mapping information, so we assume a broken 1:1
- // glyph model here. This is plainly wrong.
- return glyphIndex;
- }
-
- public int[] getGlyphCharIndices (int beginGlyphIndex,
- int numEntries,
- int[] codeReturn)
- {
- int ix[] = codeReturn;
- if (ix == null)
- ix = new int[numEntries];
-
- for (int i = 0; i < numEntries; i++)
- ix[i] = getGlyphCharIndex (beginGlyphIndex + i);
- return ix;
- }
-
- public int getGlyphCode (int glyphIndex)
- {
- return codes[glyphIndex];
- }
-
- public int[] getGlyphCodes (int beginGlyphIndex, int numEntries,
- int[] codeReturn)
- {
- if (codeReturn == null)
- codeReturn = new int[numEntries];
-
- System.arraycopy(codes, beginGlyphIndex, codeReturn, 0, numEntries);
- return codeReturn;
- }
-
- public Shape getGlyphLogicalBounds (int i)
- {
- return new Rectangle2D.Double (extents[8*i], extents[8*i + 1],
- extents[8*i + 2], extents[8*i + 3]);
- }
-
- public GlyphMetrics getGlyphMetrics (int i)
- {
- // FIXME: pango does not yield vertical layout information at the
- // moment.
-
- boolean is_horizontal = true;
- double advanceX = extents[8*i + 2]; // "logical width" == advanceX
- double advanceY = 0;
-
- return new GlyphMetrics (is_horizontal,
- (float) advanceX, (float) advanceY,
- (Rectangle2D) getGlyphVisualBounds(i),
- GlyphMetrics.STANDARD);
- }
-
- public Shape getGlyphOutline (int glyphIndex)
- {
- throw new UnsupportedOperationException ();
- }
-
- public Shape getGlyphOutline (int glyphIndex, float x, float y)
- {
- throw new UnsupportedOperationException ();
- }
-
- public Rectangle getGlyphPixelBounds (int i,
- FontRenderContext renderFRC,
- float x, float y)
- {
- return new Rectangle((int) x, (int) y,
- (int) extents[8*i + 6], (int) extents[8*i + 7]);
- }
-
- public Point2D getGlyphPosition (int i)
- {
- return new Point2D.Double (extents[10*i + 8],
- extents[10*i + 9]);
- }
-
- public float[] getGlyphPositions (int beginGlyphIndex,
- int numEntries,
- float[] positionReturn)
- {
- float fx[] = positionReturn;
- if (fx == null)
- fx = new float[numEntries * 2];
-
- for (int i = 0; i < numEntries; ++i)
- {
- fx[2*i ] = (float) extents[10*i + 8];
- fx[2*i + 1] = (float) extents[10*i + 9];
- }
- return fx;
- }
-
- public AffineTransform getGlyphTransform (int glyphIndex)
- {
- // Glyphs don't have independent transforms in these simple glyph
- // vectors; docs specify null is an ok return here.
- return null;
- }
-
- public Shape getGlyphVisualBounds (int i)
- {
- return new Rectangle2D.Double(extents[8*i + 4], extents[8*i + 5],
- extents[8*i + 6], extents[8*i + 7]);
- }
-
- public int getLayoutFlags ()
- {
- return 0;
- }
-
- public Rectangle2D getLogicalBounds ()
- {
- return allLogical;
- }
-
- public int getNumGlyphs ()
- {
- return codes.length;
- }
-
- public Shape getOutline ()
- {
- throw new UnsupportedOperationException ();
- }
-
- public Rectangle getPixelBounds (FontRenderContext renderFRC,
- float x, float y)
- {
- return new Rectangle((int)x,
- (int)y,
- (int) allVisual.getWidth(),
- (int) allVisual.getHeight());
- }
-
- public Rectangle2D getVisualBounds ()
- {
- return allVisual;
- }
-
- public void performDefaultLayout ()
- {
- }
-
- public void setGlyphPosition (int i, Point2D newPos)
- {
- extents[8*i ] = newPos.getX();
- extents[8*i + 1] = newPos.getY();
-
- extents[8*i + 4] = newPos.getX();
- extents[8*i + 5] = newPos.getY();
- }
-
- public void setGlyphTransform (int glyphIndex,
- AffineTransform newTX)
- {
- // not yet.. maybe not ever?
- throw new UnsupportedOperationException ();
- }
-
- public boolean equals(GlyphVector gv)
- {
- if (gv == null)
- return false;
-
- if (! (gv instanceof GdkGlyphVector))
- return false;
-
- GdkGlyphVector ggv = (GdkGlyphVector) gv;
-
- if ((ggv.codes.length != this.codes.length)
- || (ggv.extents.length != this.extents.length))
- return false;
-
- if ((ggv.font == null && this.font != null)
- || (ggv.font != null && this.font == null)
- || (!ggv.font.equals(this.font)))
- return false;
-
- if ((ggv.fontRenderContext == null && this.fontRenderContext != null)
- || (ggv.fontRenderContext != null && this.fontRenderContext == null)
- || (!ggv.fontRenderContext.equals(this.fontRenderContext)))
- return false;
-
- for (int i = 0; i < ggv.codes.length; ++i)
- if (ggv.codes[i] != this.codes[i])
- return false;
-
- for (int i = 0; i < ggv.extents.length; ++i)
- if (ggv.extents[i] != this.extents[i])
- return false;
-
- return true;
- }
-
- public GlyphJustificationInfo getGlyphJustificationInfo(int idx)
- {
- throw new UnsupportedOperationException ();
- }
-
- public Shape getOutline(float x, float y)
- {
- throw new UnsupportedOperationException ();
- }
-
-}
diff --git a/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java b/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java
index 6cf7310a5..147f8f3e6 100644
--- a/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java
+++ b/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java
@@ -1,5 +1,5 @@
/* GdkGraphicsConfiguration.java -- describes characteristics of graphics
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -42,26 +42,33 @@ import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.ImageCapabilities;
import java.awt.Rectangle;
-import java.awt.Toolkit;
+import java.awt.Transparency;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
import java.awt.image.VolatileImage;
public class GdkGraphicsConfiguration
extends GraphicsConfiguration
{
GdkScreenGraphicsDevice gdkScreenGraphicsDevice;
- ColorModel cm;
- Rectangle bounds;
+
+ ColorModel opaqueColorModel;
+ ColorModel bitmaskColorModel;
+
+ ColorModel translucentColorModel;
+
public GdkGraphicsConfiguration(GdkScreenGraphicsDevice dev)
{
- this.gdkScreenGraphicsDevice = dev;
- cm = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).getColorModel();
- bounds = ((GtkToolkit) Toolkit.getDefaultToolkit()).getBounds();
+ gdkScreenGraphicsDevice = dev;
+
+ opaqueColorModel = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF, 0);
+ bitmaskColorModel = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF, 0x1000000);
+ translucentColorModel = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000);
}
public GraphicsDevice getDevice()
@@ -94,12 +101,21 @@ public class GdkGraphicsConfiguration
public ColorModel getColorModel()
{
- return cm;
+ return opaqueColorModel;
}
public ColorModel getColorModel(int transparency)
{
- return getColorModel();
+ switch (transparency)
+ {
+ case Transparency.OPAQUE:
+ return opaqueColorModel;
+ case Transparency.BITMASK:
+ return bitmaskColorModel;
+ default:
+ case Transparency.TRANSLUCENT:
+ return translucentColorModel;
+ }
}
public AffineTransform getDefaultTransform()
@@ -116,7 +132,7 @@ public class GdkGraphicsConfiguration
public Rectangle getBounds()
{
- return bounds;
+ return gdkScreenGraphicsDevice.getBounds();
}
public BufferCapabilities getBufferCapabilities()
@@ -133,8 +149,8 @@ public class GdkGraphicsConfiguration
public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency)
{
- // FIXME: implement
- return null;
+ // FIXME: support the transparency argument
+ return new GtkVolatileImage(width, height);
}
}
diff --git a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
index b2615a912..035819d1c 100644
--- a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
+++ b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
@@ -1,5 +1,5 @@
/* GdkGraphicsEnvironment.java -- information about the graphics environment
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -43,30 +43,63 @@ import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
-import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.util.Locale;
public class GdkGraphicsEnvironment extends GraphicsEnvironment
{
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+ private GdkScreenGraphicsDevice defaultDevice;
+
+ private GdkScreenGraphicsDevice[] devices;
+
+ static
+ {
+ System.loadLibrary("gtkpeer");
+
+ initStaticState ();
+ }
+
+ static native void initStaticState();
+
public GdkGraphicsEnvironment ()
{
+ nativeInitState();
}
+
+ native void nativeInitState();
public GraphicsDevice[] getScreenDevices ()
{
- // FIXME: Support multiple screens, since GDK can.
- return new GraphicsDevice[] { new GdkScreenGraphicsDevice (this) };
+ if (devices == null)
+ {
+ devices = nativeGetScreenDevices();
+ }
+
+ return (GraphicsDevice[]) devices.clone();
}
+
+ private native GdkScreenGraphicsDevice[] nativeGetScreenDevices();
public GraphicsDevice getDefaultScreenDevice ()
{
if (GraphicsEnvironment.isHeadless ())
throw new HeadlessException ();
-
- return new GdkScreenGraphicsDevice (this);
+
+ synchronized (GdkGraphicsEnvironment.class)
+ {
+ if (defaultDevice == null)
+ {
+ defaultDevice = nativeGetDefaultScreenDevice();
+ }
+ }
+
+ return defaultDevice;
}
+
+ private native GdkScreenGraphicsDevice nativeGetDefaultScreenDevice();
public Graphics2D createGraphics (BufferedImage image)
{
@@ -89,10 +122,10 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment
{
String[] family_names;
int array_size;
-
+
array_size = nativeGetNumFontFamilies();
family_names = new String[array_size];
-
+
nativeGetFontFamilies(family_names);
return family_names;
}
@@ -101,4 +134,5 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment
{
throw new java.lang.UnsupportedOperationException ();
}
+
}
diff --git a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
index 4e6181f0e..cd047f267 100644
--- a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
+++ b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
@@ -103,8 +103,15 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
native void pumpBytes (byte[] bytes, int len) throws IOException;
native void pumpDone () throws IOException;
native void finish (boolean needsClose);
- static native void streamImage(int[] bytes, String format, int width, int height, boolean hasAlpha, DataOutput sink);
-
+
+ /**
+ * Converts given image to bytes.
+ * Will call the GdkPixbufWriter for each chunk.
+ */
+ static native void streamImage(int[] bytes, String format,
+ int width, int height,
+ boolean hasAlpha, GdkPixbufWriter writer);
+
// gdk-pixbuf provids data in RGBA format
static final ColorModel cm = new DirectColorModel (32, 0xff000000,
0x00ff0000,
@@ -461,7 +468,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
}
private static class GdkPixbufWriter
- extends ImageWriter
+ extends ImageWriter implements Runnable
{
String ext;
public GdkPixbufWriter(GdkPixbufWriterSpi ownerSpi, Object ext)
@@ -519,14 +526,106 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
model = img.getColorModel();
}
+ Thread workerThread = new Thread(this, "GdkPixbufWriter");
+ workerThread.start();
processImageStarted(1);
synchronized(pixbufLock)
{
streamImage(pixels, this.ext, width, height, model.hasAlpha(),
- (DataOutput) this.getOutput());
+ this);
}
+ synchronized(data)
+ {
+ data.add(DATADONE);
+ data.notifyAll();
+ }
+
+ while (workerThread.isAlive())
+ {
+ try
+ {
+ workerThread.join();
+ }
+ catch (InterruptedException ioe)
+ {
+ // Ignored.
+ }
+ }
+
+ if (exception != null)
+ throw exception;
+
processImageComplete();
}
+
+ /**
+ * Object marking end of data from native streamImage code.
+ */
+ private static final Object DATADONE = new Object();
+
+ /**
+ * Holds the data gotten from the native streamImage code.
+ * A worker thread will pull data out.
+ * Needs to be synchronized for access.
+ * The special object DATADONE is added when all data has been delivered.
+ */
+ private ArrayList data = new ArrayList();
+
+ /**
+ * Holds any IOException thrown by the run method that needs
+ * to be rethrown by the write method.
+ */
+ private IOException exception;
+
+ /** Callback for streamImage native code. **/
+ private void write(byte[] bs)
+ {
+ synchronized(data)
+ {
+ data.add(bs);
+ data.notifyAll();
+ }
+ }
+
+ public void run()
+ {
+ boolean done = false;
+ while (!done)
+ {
+ synchronized(data)
+ {
+ while (data.isEmpty())
+ {
+ try
+ {
+ data.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ /* ignore */
+ }
+ }
+
+ Object o = data.remove(0);
+ if (o == DATADONE)
+ done = true;
+ else
+ {
+ DataOutput out = (DataOutput) getOutput();
+ try
+ {
+ out.write((byte[]) o);
+ }
+ catch (IOException ioe)
+ {
+ // We are only interested in the first exception.
+ if (exception == null)
+ exception = ioe;
+ }
+ }
+ }
+ }
+ }
}
private static class GdkPixbufReader
diff --git a/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java b/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
index b5d1237a4..62116a322 100644
--- a/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
+++ b/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
@@ -1,5 +1,5 @@
/* GdkScreenGraphicsDevice.java -- information about a screen device
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,44 +38,110 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Dimension;
import java.awt.DisplayMode;
+import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
-import java.awt.Toolkit;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.util.ArrayList;
-public class GdkScreenGraphicsDevice extends GraphicsDevice
+class GdkScreenGraphicsDevice extends GraphicsDevice
{
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+ private Window fullscreenWindow;
+
+ private boolean oldWindowDecorationState;
+
+ private Rectangle oldWindowBounds;
+
+ private Rectangle bounds;
+
+ private GdkGraphicsConfiguration[] configurations;
+
+ /** The <code>GdkGraphicsEnvironment</code> instance that created this
+ * <code>GdkScreenGraphicsDevice</code>. This is only needed for native
+ * methods which need to access the 'native_state' field storing a pointer
+ * to a GdkDisplay object.
+ */
GdkGraphicsEnvironment env;
+
+ /** An identifier that is created by Gdk
+ */
+ String idString;
+
+ /** The display modes supported by this <code>GdkScreenGraphicsDevice</code>.
+ * If the array is <code>null</code> <code>nativeGetDisplayModes</code> has
+ * to be called.
+ */
+ X11DisplayMode[] displayModes;
- public GdkScreenGraphicsDevice (GdkGraphicsEnvironment e)
- {
- super ();
+ /** The non-changeable display mode of this <code>GdkScreenGraphicsDevice
+ * </code>. This field gets initialized by the {@link #init()} method. If it
+ * is still <code>null</code> afterwards, the XRandR extension is available
+ * and display mode changes are possible. If it is non-null XRandR is not
+ * available, no display mode changes are possible and no other native
+ * method must be called.
+ */
+ DisplayMode fixedDisplayMode;
+
+ static
+ {
+ System.loadLibrary("gtkpeer");
+
+ initStaticState ();
+ }
+
+ static native void initStaticState();
+
+ GdkScreenGraphicsDevice (GdkGraphicsEnvironment e)
+ {
+ super();
env = e;
+
+ configurations = new GdkGraphicsConfiguration[1];
+ configurations[0] = new GdkGraphicsConfiguration(this);
}
+ /** This method is called from the native side immediately after
+ * the constructor is run.
+ */
+ void init()
+ {
+ fixedDisplayMode = nativeGetFixedDisplayMode(env);
+ }
+
+ /** Depending on the availability of the XRandR extension the method returns
+ * the screens' non-changeable display mode or null, meaning that XRandR can
+ * handle display mode changes.
+ */
+ native DisplayMode nativeGetFixedDisplayMode(GdkGraphicsEnvironment env);
+
public int getType ()
{
+ // Gdk manages only raster screens.
return GraphicsDevice.TYPE_RASTER_SCREEN;
}
public String getIDstring ()
{
- // FIXME: query X for this string
- return "default GDK device ID string";
+ if (idString == null)
+ idString = nativeGetIDString();
+
+ return idString;
}
+
+ private native String nativeGetIDString();
public GraphicsConfiguration[] getConfigurations ()
{
- // FIXME: query X for the list of possible configurations
- return new GraphicsConfiguration [] { new GdkGraphicsConfiguration(this) };
+ return (GraphicsConfiguration[]) configurations.clone();
}
-
+
public GraphicsConfiguration getDefaultConfiguration ()
{
-
- // FIXME: query X for default configuration
- return new GdkGraphicsConfiguration(this);
+ return configurations[0];
}
@@ -89,23 +155,193 @@ public class GdkScreenGraphicsDevice extends GraphicsDevice
*/
public DisplayMode getDisplayMode()
{
- // determine display mode
- Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
- DisplayMode mode = new DisplayMode(dim.width, dim.height, 0,
- DisplayMode.REFRESH_RATE_UNKNOWN);
- return mode;
+ if (fixedDisplayMode != null)
+ return fixedDisplayMode;
+
+ synchronized (this)
+ {
+ if (displayModes == null)
+ displayModes = nativeGetDisplayModes(env);
+ }
+
+ int index = nativeGetDisplayModeIndex(env);
+ int rate = nativeGetDisplayModeRate(env);
+
+ return new DisplayMode(displayModes[index].width,
+ displayModes[index].height,
+ DisplayMode.BIT_DEPTH_MULTI,
+ rate);
+ }
+
+ native int nativeGetDisplayModeIndex(GdkGraphicsEnvironment env);
+
+ native int nativeGetDisplayModeRate(GdkGraphicsEnvironment env);
+
+ public DisplayMode[] getDisplayModes()
+ {
+ if (fixedDisplayMode != null)
+ return new DisplayMode[] { fixedDisplayMode };
+
+ synchronized (this)
+ {
+ if (displayModes == null)
+ displayModes = nativeGetDisplayModes(env);
+ }
+
+ ArrayList list = new ArrayList();
+ for(int i=0;i<displayModes.length;i++)
+ for(int j=0;j<displayModes[i].rates.length;j++)
+ list.add(new DisplayMode(displayModes[i].width,
+ displayModes[i].height,
+ DisplayMode.BIT_DEPTH_MULTI,
+ displayModes[i].rates[j]));
+
+ return (DisplayMode[]) list.toArray(new DisplayMode[list.size()]);
}
+
+ native X11DisplayMode[] nativeGetDisplayModes(GdkGraphicsEnvironment env);
/**
- * This device does not yet support fullscreen exclusive mode, so this
- * returns <code>false</code>.
+ * Real fullscreen exclusive mode is not supported.
*
* @return <code>false</code>
* @since 1.4
*/
public boolean isFullScreenSupported()
{
- return false;
+ return true;
+ }
+
+ public boolean isDisplayChangeSupported()
+ {
+ return fixedDisplayMode == null;
+ }
+
+ public void setDisplayMode(DisplayMode dm)
+ {
+ if (fixedDisplayMode != null)
+ throw new UnsupportedOperationException("Cannnot change display mode.");
+
+ if (dm == null)
+ throw new IllegalArgumentException("DisplayMode must not be null.");
+
+ synchronized (this)
+ {
+ if (displayModes == null)
+ displayModes = nativeGetDisplayModes(env);
+ }
+
+ for (int i=0; i<displayModes.length; i++)
+ if (displayModes[i].width == dm.getWidth()
+ && displayModes[i].height == dm.getHeight())
+ {
+ synchronized (this)
+ {
+ nativeSetDisplayMode(env,
+ i,
+ (short) dm.getRefreshRate());
+
+ bounds = null;
+ }
+
+ return;
+ }
+
+ throw new IllegalArgumentException("Mode not supported by this device.");
+ }
+
+ native void nativeSetDisplayMode(GdkGraphicsEnvironment env,
+ int index, short rate);
+
+ /** A class that simply encapsulates the X11 display mode data.
+ */
+ static class X11DisplayMode
+ {
+ short[] rates;
+ int width;
+ int height;
+
+ X11DisplayMode(int width, int height, short[] rates)
+ {
+ this.width = width;
+ this.height = height;
+ this.rates = rates;
+ }
+
+ }
+
+ public void setFullScreenWindow(Window w)
+ {
+ // Bring old fullscreen window back into its original state.
+ if (fullscreenWindow != null && w != fullscreenWindow)
+ {
+ if (fullscreenWindow instanceof Frame)
+ {
+ // Decoration state can only be switched when the peer is
+ // non-existent. That means we have to dispose the
+ // Frame.
+ Frame f = (Frame) fullscreenWindow;
+ if (oldWindowDecorationState != f.isUndecorated())
+ {
+ f.dispose();
+ f.setUndecorated(oldWindowDecorationState);
+ }
+ }
+
+ fullscreenWindow.setBounds(oldWindowBounds);
+
+ if (!fullscreenWindow.isVisible())
+ fullscreenWindow.setVisible(true);
+ }
+
+ // If applicable remove decoration, then maximize the window and
+ // bring it to the foreground.
+ if (w != null)
+ {
+ if (w instanceof Frame)
+ {
+ Frame f = (Frame) w;
+ oldWindowDecorationState = f.isUndecorated();
+ if (!oldWindowDecorationState)
+ {
+ f.dispose();
+ f.setUndecorated(true);
+ }
+ }
+
+ oldWindowBounds = w.getBounds();
+
+ DisplayMode dm = getDisplayMode();
+
+ w.setBounds(0, 0, dm.getWidth(), dm.getHeight());
+
+ if (!w.isVisible())
+ w.setVisible(true);
+
+ w.requestFocus();
+ w.toFront();
+
+ }
+
+ fullscreenWindow = w;
+ }
+
+ public Window getFullScreenWindow()
+ {
+ return fullscreenWindow;
+ }
+
+ Rectangle getBounds()
+ {
+ synchronized(this)
+ {
+ if (bounds == null)
+ bounds = nativeGetBounds();
+ }
+
+ return bounds;
}
+
+ native Rectangle nativeGetBounds();
}
diff --git a/gnu/java/awt/peer/gtk/GdkTextLayout.java b/gnu/java/awt/peer/gtk/GdkTextLayout.java
deleted file mode 100644
index d6b3de8c0..000000000
--- a/gnu/java/awt/peer/gtk/GdkTextLayout.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/* GdkTextLayout.java
- Copyright (C) 2003, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.java.awt.peer.gtk;
-
-import gnu.classpath.Configuration;
-import gnu.java.awt.peer.ClasspathTextLayoutPeer;
-
-import java.awt.Font;
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphMetrics;
-import java.awt.font.GlyphVector;
-import java.awt.font.TextAttribute;
-import java.awt.font.TextHitInfo;
-import java.awt.font.TextLayout;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Rectangle2D;
-import java.text.AttributedCharacterIterator;
-import java.text.AttributedString;
-import java.text.CharacterIterator;
-
-/**
- * This is an implementation of the text layout peer interface which
- * delegates all the hard work to pango.
- *
- * @author Graydon Hoare
- */
-
-public class GdkTextLayout
- implements ClasspathTextLayoutPeer
-{
- // native side, plumbing, etc.
- static
- {
- System.loadLibrary("gtkpeer");
-
- initStaticState ();
- }
- private native void setText(String str);
- private native void setFont(GdkFontPeer font);
- private native void getExtents(double[] inkExtents,
- double[] logExtents);
- private native void indexToPos(int idx, double[] pos);
-
- private native void initState ();
-
- private native void dispose ();
-
- private native void cairoDrawGdkTextLayout(CairoGraphics2D g, float x, float y);
-
- static native void initStaticState();
-
- private final int native_state = GtkGenericPeer.getUniqueInteger ();
-
- protected void finalize ()
- {
- dispose ();
- }
-
- // we hold on to these to make sure we can render when presented
- // with non-GdkGraphics2D paint targets
- private AttributedString attributedString;
- private FontRenderContext fontRenderContext;
-
- public GdkTextLayout(AttributedString str, FontRenderContext frc)
- {
- initState();
- attributedString = str;
- fontRenderContext = frc;
- AttributedCharacterIterator aci = str.getIterator();
- char[] chars = new char[aci.getEndIndex() - aci.getBeginIndex()];
- for(int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++)
- chars[i] = aci.setIndex(i);
- setText(new String(chars));
-
- Object fnt = aci.getAttribute(TextAttribute.FONT);
- if (fnt != null && fnt instanceof Font)
- setFont( (GdkFontPeer) ((Font)fnt).getPeer() );
- }
-
- protected class CharacterIteratorProxy
- implements CharacterIterator
- {
- public CharacterIterator target;
- public int begin;
- public int limit;
- public int index;
-
- public CharacterIteratorProxy (CharacterIterator ci)
- {
- target = ci;
- }
-
- public int getBeginIndex ()
- {
- return begin;
- }
-
- public int getEndIndex ()
- {
- return limit;
- }
-
- public int getIndex ()
- {
- return index;
- }
-
- public char setIndex (int idx)
- throws IllegalArgumentException
- {
- if (idx < begin || idx >= limit)
- throw new IllegalArgumentException ();
- char ch = target.setIndex (idx);
- index = idx;
- return ch;
- }
-
- public char first ()
- {
- int save = target.getIndex ();
- char ch = target.setIndex (begin);
- target.setIndex (save);
- return ch;
- }
-
- public char last ()
- {
- if (begin == limit)
- return this.first ();
-
- int save = target.getIndex ();
- char ch = target.setIndex (limit - 1);
- target.setIndex (save);
- return ch;
- }
-
- public char current ()
- {
- return target.current();
- }
-
- public char next ()
- {
- if (index >= limit - 1)
- return CharacterIterator.DONE;
- else
- {
- index++;
- return target.next();
- }
- }
-
- public char previous ()
- {
- if (index <= begin)
- return CharacterIterator.DONE;
- else
- {
- index--;
- return target.previous ();
- }
- }
-
- public Object clone ()
- {
- CharacterIteratorProxy cip = new CharacterIteratorProxy (this.target);
- cip.begin = this.begin;
- cip.limit = this.limit;
- cip.index = this.index;
- return cip;
- }
-
- }
-
-
- // public side
-
- public void draw (Graphics2D g2, float x, float y)
- {
- cairoDrawGdkTextLayout((CairoGraphics2D)g2, x, y);
- }
-
- public TextHitInfo getStrongCaret (TextHitInfo hit1,
- TextHitInfo hit2)
- {
- throw new Error("not implemented");
- }
-
- public byte getBaseline ()
- {
- throw new Error("not implemented");
- }
-
- public boolean isLeftToRight ()
- {
- throw new Error("not implemented");
- }
-
- public boolean isVertical ()
- {
- throw new Error("not implemented");
- }
-
- public float getAdvance ()
- {
- throw new Error("not implemented");
- }
-
- public float getAscent ()
- {
- throw new Error("not implemented");
- }
-
- public float getDescent ()
- {
- throw new Error("not implemented");
- }
-
- public float getLeading ()
- {
- throw new Error("not implemented");
- }
-
- public int getCharacterCount ()
- {
- throw new Error("not implemented");
- }
-
- public byte getCharacterLevel (int index)
- {
- throw new Error("not implemented");
- }
-
- public float[] getBaselineOffsets ()
- {
- throw new Error("not implemented");
- }
-
- public Shape getBlackBoxBounds (int firstEndpoint, int secondEndpoint)
- {
- throw new Error("not implemented");
- }
-
- public Rectangle2D getBounds ()
- {
- double[] inkExtents = new double[4];
- double[] logExtents = new double[4];
- getExtents(inkExtents, logExtents);
- return new Rectangle2D.Double(logExtents[0], logExtents[1],
- logExtents[2], logExtents[3]);
- }
-
- public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds)
- {
- throw new Error("not implemented");
- }
-
- public Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds)
- {
- throw new Error("not implemented");
- }
-
- public Shape[] getCaretShapes (int offset, Rectangle2D bounds,
- TextLayout.CaretPolicy policy)
- {
- throw new Error("not implemented");
- }
-
- public Shape getLogicalHighlightShape (int firstEndpoint, int secondEndpoint,
- Rectangle2D bounds)
- {
- AffineTransform at = new AffineTransform();
- GeneralPath gp = new GeneralPath();
- double [] rect = new double[4];
- Rectangle2D tmp = new Rectangle2D.Double();
- for (int i = firstEndpoint; i <= secondEndpoint; ++i)
- {
- indexToPos(i, rect);
- tmp.setRect(rect[0], rect[1], rect[2], rect[3]);
- Rectangle2D.intersect(tmp, bounds, tmp);
- gp.append(tmp.getPathIterator(at), false);
- }
- return gp;
- }
-
- public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
- TextHitInfo secondEndpoint)
- {
- throw new Error("not implemented");
- }
-
- public TextHitInfo getNextLeftHit (int offset, TextLayout.CaretPolicy policy)
- {
- throw new Error("not implemented");
- }
- public TextHitInfo getNextRightHit (int offset, TextLayout.CaretPolicy policy)
- {
- throw new Error("not implemented");
- }
- public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
- {
- throw new Error("not implemented");
- }
- public TextHitInfo getVisualOtherHit (TextHitInfo hit)
- {
- throw new Error("not implemented");
- }
-
- public float getVisibleAdvance ()
- {
- throw new Error("not implemented");
- }
-
- public native Shape getOutline (AffineTransform tx);
-
- public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
- TextHitInfo secondEndpoint,
- Rectangle2D bounds)
- {
- throw new Error("not implemented");
- }
-
-
- public TextLayout getJustifiedLayout (float justificationWidth)
- {
- throw new Error("not implemented");
- }
-
- public void handleJustify (float justificationWidth)
- {
- throw new Error("not implemented");
- }
-
- public Object clone ()
- {
- throw new Error("not implemented");
- }
-
- public int hashCode ()
- {
- throw new Error("not implemented");
- }
-
- public boolean equals (ClasspathTextLayoutPeer tl)
- {
- throw new Error("not implemented");
- }
-
- public String toString ()
- {
- throw new Error("not implemented");
- }
-
-}
diff --git a/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
index 094aa3c03..1c5400c27 100644
--- a/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
@@ -40,20 +40,32 @@ package gnu.java.awt.peer.gtk;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
-import java.awt.peer.CheckboxPeer;
-
import java.awt.event.ItemEvent;
+import java.awt.peer.CheckboxPeer;
+import java.util.WeakHashMap;
+/**
+ * This class wraps either a GtkCheckButton or a GtkOptionButton
+ * depending on if this peer's owner belongs to a CheckboxGroup.
+ */
public class GtkCheckboxPeer extends GtkComponentPeer
implements CheckboxPeer
{
- // Group from last time it was set.
- public GtkCheckboxGroupPeer old_group;
+ // The CheckboxGroup to which this GtkCheckboxPeer's owner belongs.
+ public CheckboxGroup current_group;
// The current state of the GTK checkbox.
- private boolean currentState;
+ private boolean currentState;
+
+ // A map from CheckboxGroup to GSList* GTK option group pointer.
+ private static WeakHashMap groupMap = new WeakHashMap();
+
+ public native void createCheckButton ();
+ public native void createRadioButton (long groupPointer);
- public native void create (GtkCheckboxGroupPeer group);
- public native void nativeSetCheckboxGroup (GtkCheckboxGroupPeer group);
+ public native void addToGroup (long groupPointer);
+ public native void removeFromGroup ();
+ public native void switchToGroup (long groupPointer);
+
public native void connectSignals ();
/**
@@ -68,17 +80,47 @@ public class GtkCheckboxPeer extends GtkComponentPeer
super (c);
}
- // FIXME: we must be able to switch between a checkbutton and a
- // radiobutton dynamically.
public void create ()
{
Checkbox checkbox = (Checkbox) awtComponent;
- CheckboxGroup g = checkbox.getCheckboxGroup ();
- old_group = GtkCheckboxGroupPeer.getCheckboxGroupPeer (g);
- create (old_group);
+ current_group = checkbox.getCheckboxGroup ();
+ if (current_group == null)
+ {
+ // Initially we're not part of a group so we're backed by a
+ // GtkCheckButton.
+ createCheckButton();
+ }
+ else
+ {
+ // Initially we're part of a group.
+
+ // See if this group is already stored in our map.
+ Long groupPointer = null;
+ synchronized (groupMap)
+ {
+ groupPointer = (Long) groupMap.get(current_group);
+ }
+
+ if (groupPointer == null)
+ {
+ // We don't know about this group. Create a new native
+ // group pointer for this group and store it in our map.
+ createRadioButton(0);
+ }
+ else
+ {
+ // We already know about this group. Pass the
+ // corresponding native group pointer value to the native
+ // create method.
+ createRadioButton(groupPointer.longValue());
+ }
+ }
currentState = checkbox.getState();
gtkToggleButtonSetActive(currentState);
- gtkButtonSetLabel (checkbox.getLabel ());
+
+ String label = checkbox.getLabel();
+ if (label != null)
+ gtkButtonSetLabel(label);
}
/**
@@ -87,7 +129,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer
* event since events should only be posted for user initiated
* clicks on the GtkCheckButton.
*/
- synchronized public void setState (boolean state)
+ public synchronized void setState (boolean state)
{
if (currentState != state)
{
@@ -103,21 +145,87 @@ public class GtkCheckboxPeer extends GtkComponentPeer
public void setCheckboxGroup (CheckboxGroup group)
{
- GtkCheckboxGroupPeer gp
- = GtkCheckboxGroupPeer.getCheckboxGroupPeer (group);
- if (gp != old_group)
+ if (current_group == null && group != null)
{
- if (old_group != null)
- old_group.remove (this);
- nativeSetCheckboxGroup (gp);
- old_group = gp;
+ // This peer's owner is currently not in a group, and now
+ // we're adding it to a group. This means that the backing
+ // GtkWidget will change from a GtkCheckButton to a
+ // GtkRadioButton.
+
+ current_group = group;
+
+ // See if the new group is already stored in our map.
+ Long groupPointer = null;
+ synchronized (groupMap)
+ {
+ groupPointer = (Long) groupMap.get(current_group);
+ }
+
+ if (groupPointer == null)
+ {
+ // We don't know about this group. Create a new native
+ // group pointer for this group and store it in our map.
+ addToGroup(0);
+ }
+ else
+ {
+ // We already know about this group. Pass the
+ // corresponding native group pointer value to the native
+ // create method.
+ addToGroup(groupPointer.longValue());
+ }
+ }
+ else if (current_group != null && group == null)
+ {
+ // This peer's owner is currently in a group, and now we're
+ // removing it from a group. This means that the backing
+ // GtkWidget will change from a GtkRadioButton to a
+ // GtkCheckButton.
+ removeFromGroup();
+ current_group = null;
+ }
+ else if (current_group == null && group == null)
+ {
+ // This peer's owner is currently not in a group, and we're
+ // not adding it to a group, so simply return.
+ return;
+ }
+ else if (current_group != group)
+ {
+ // This peer's owner is currently in a group, and now we're
+ // putting it in another group. This means that we must
+ // remove the backing GtkRadioButton from one group and add it
+ // to the other group.
+
+ current_group = group;
+
+ // See if the new group is already stored in our map.
+ Long groupPointer = null;
+ synchronized (groupMap)
+ {
+ groupPointer = (Long) groupMap.get(current_group);
+ }
+
+ if (groupPointer == null)
+ {
+ // We don't know about this group. Create a new native
+ // group pointer for this group and store it in our map.
+ switchToGroup(0);
+ }
+ else
+ {
+ // We already know about this group. Pass the
+ // corresponding native group pointer value to the native
+ // create method.
+ switchToGroup(groupPointer.longValue());
+ }
}
}
// Override the superclass postItemEvent so that the peer doesn't
// need information that we have.
// called back by native side: item_toggled_cb
- synchronized public void postItemEvent(Object item, boolean state)
+ public synchronized void postItemEvent(Object item, boolean state)
{
// Only fire event is state actually changed.
if (currentState != state)
@@ -127,13 +235,17 @@ public class GtkCheckboxPeer extends GtkComponentPeer
state ? ItemEvent.SELECTED : ItemEvent.DESELECTED);
}
}
+
+ public void addToGroupMap(long groupPointer)
+ {
+ synchronized (groupMap)
+ {
+ groupMap.put(current_group, new Long (groupPointer));
+ }
+ }
public void dispose ()
{
- // Notify the group so that the native state can be cleaned up
- // appropriately.
- if (old_group != null)
- old_group.remove (this);
super.dispose ();
}
}
diff --git a/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
index 625855f01..dcbac1259 100644
--- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
@@ -52,6 +52,8 @@ import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.ItemSelectable;
@@ -647,8 +649,10 @@ public class GtkComponentPeer extends GtkGenericPeer
public GraphicsConfiguration getGraphicsConfiguration ()
{
- // FIXME: just a stub for now.
- return null;
+ // FIXME: The component might be showing on a non-default screen.
+ GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice dev = env.getDefaultScreenDevice();
+ return dev.getDefaultConfiguration();
}
public void setEventMask (long mask)
diff --git a/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/gnu/java/awt/peer/gtk/GtkLabelPeer.java
index bbf4230b3..02db90d72 100644
--- a/gnu/java/awt/peer/gtk/GtkLabelPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkLabelPeer.java
@@ -56,7 +56,7 @@ public class GtkLabelPeer extends GtkComponentPeer
native void nativeSetAlignment (float alignment);
- public native void setText(String text);
+ public native void setNativeText(String text);
native void setNativeBounds (int x, int y, int width, int height);
// Because this is a composite widget, we need to retrieve the
@@ -69,6 +69,12 @@ public class GtkLabelPeer extends GtkComponentPeer
create (label.getText (), getGtkAlignment (label.getAlignment ()));
}
+ public void setText(String text)
+ {
+ if (text != null)
+ setNativeText(text);
+ }
+
public GtkLabelPeer (Label l)
{
super (l);
diff --git a/gnu/java/awt/peer/gtk/GtkToolkit.java b/gnu/java/awt/peer/gtk/GtkToolkit.java
index 163fc52f7..fdd7e09cb 100644
--- a/gnu/java/awt/peer/gtk/GtkToolkit.java
+++ b/gnu/java/awt/peer/gtk/GtkToolkit.java
@@ -39,32 +39,82 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import gnu.classpath.Configuration;
import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.dnd.GtkMouseDragGestureRecognizer;
+import gnu.java.awt.dnd.peer.gtk.GtkDragSourceContextPeer;
import gnu.java.awt.peer.ClasspathFontPeer;
-import gnu.java.awt.peer.ClasspathTextLayoutPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
-import java.awt.*;
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.awt.PrintJob;
+import java.awt.Rectangle;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureRecognizer;
+import java.awt.dnd.DragSource;
import java.awt.dnd.peer.DragSourceContextPeer;
-import java.awt.font.FontRenderContext;
import java.awt.im.InputMethodHighlight;
-import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
-import java.awt.image.ImageConsumer;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
-import java.awt.peer.*;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
import java.io.InputStream;
import java.net.URL;
-import java.text.AttributedString;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Hashtable;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
@@ -310,6 +360,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
public PrintJob getPrintJob (Frame frame, String jobtitle, Properties props)
{
+ SecurityManager sm;
+ sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPrintJobAccess();
+
return null;
}
@@ -528,12 +583,6 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
}
}
- public ClasspathTextLayoutPeer getClasspathTextLayoutPeer (AttributedString str,
- FontRenderContext frc)
- {
- return new GdkTextLayout(str, frc);
- }
-
protected EventQueue getSystemEventQueueImpl()
{
synchronized (GtkToolkit.class)
@@ -555,7 +604,18 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
{
- throw new Error("not implemented");
+ return new GtkDragSourceContextPeer(e);
+ }
+
+ public DragGestureRecognizer createDragGestureRecognizer(Class recognizer,
+ DragSource ds,
+ Component comp,
+ int actions,
+ DragGestureListener l)
+ {
+ if (recognizer.getName().equals("java.awt.dnd.MouseDragGestureRecognizer"))
+ return new GtkMouseDragGestureRecognizer(ds, comp, actions, l);
+ return null;
}
public Map mapInputMethodHighlight(InputMethodHighlight highlight)
diff --git a/gnu/java/awt/peer/gtk/GtkVolatileImage.java b/gnu/java/awt/peer/gtk/GtkVolatileImage.java
index cebb715ab..44e7b027b 100644
--- a/gnu/java/awt/peer/gtk/GtkVolatileImage.java
+++ b/gnu/java/awt/peer/gtk/GtkVolatileImage.java
@@ -50,25 +50,36 @@ public class GtkVolatileImage extends VolatileImage
int width, height;
private ImageCapabilities caps;
+ final GtkComponentPeer component;
+
/**
* Don't touch, accessed from native code.
*/
- private long nativePointer;
+ long nativePointer;
- /**
- * Offscreen image we draw to.
- */
- CairoSurface offScreen;
+ native long init(GtkComponentPeer component, int width, int height);
- private boolean needsUpdate = false;
+ native void destroy(long pointer);
- native long init(GtkComponentPeer component, int width, int height);
+ native int[] nativeGetPixels(long pointer);
+ public int[] getPixels()
+ {
+ return nativeGetPixels(nativePointer);
+ }
- native void destroy();
+ native void nativeCopyArea(long pointer, int x, int y, int w, int h, int dx,
+ int dy );
+ public void copyArea(int x, int y, int w, int h, int dx, int dy)
+ {
+ nativeCopyArea(nativePointer, x, y, w, h, dx, dy);
+ }
- native int[] getPixels();
-
- native void update(GtkImage image);
+ native void nativeDrawVolatile(long pointer, long srcPtr, int x, int y,
+ int w, int h );
+ public void drawVolatile(long srcPtr, int x, int y, int w, int h )
+ {
+ nativeDrawVolatile(nativePointer, srcPtr, x, y, w, h);
+ }
public GtkVolatileImage(GtkComponentPeer component,
int width, int height, ImageCapabilities caps)
@@ -76,8 +87,8 @@ public class GtkVolatileImage extends VolatileImage
this.width = width;
this.height = height;
this.caps = caps;
+ this.component = component;
nativePointer = init( component, width, height );
- offScreen = new CairoSurface( width, height );
}
public GtkVolatileImage(int width, int height, ImageCapabilities caps)
@@ -97,12 +108,7 @@ public class GtkVolatileImage extends VolatileImage
public void dispose()
{
- destroy();
- }
-
- void invalidate()
- {
- needsUpdate = true;
+ destroy(nativePointer);
}
public BufferedImage getSnapshot()
@@ -119,24 +125,17 @@ public class GtkVolatileImage extends VolatileImage
public Graphics2D createGraphics()
{
- invalidate();
- return offScreen.getGraphics();
+ return new VolatileImageGraphics( this );
}
public int validate(GraphicsConfiguration gc)
{
- if( needsUpdate )
- {
- update( offScreen.getGtkImage() );
- needsUpdate = false;
- return VolatileImage.IMAGE_RESTORED;
- }
return VolatileImage.IMAGE_OK;
}
public boolean contentsLost()
{
- return needsUpdate;
+ return false;
}
public ImageCapabilities getCapabilities()
diff --git a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
index 81de3d705..de67b316e 100644
--- a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
+++ b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
@@ -58,72 +58,68 @@ import java.awt.image.RenderedImage;
import java.awt.image.ImageObserver;
import java.util.WeakHashMap;
-public class VolatileImageGraphics extends CairoSurfaceGraphics
+public class VolatileImageGraphics extends ComponentGraphics
{
private GtkVolatileImage owner;
- public VolatileImageGraphics(GtkVolatileImage owner)
+ public VolatileImageGraphics(GtkVolatileImage img)
{
- super( owner.offScreen );
- this.owner = owner;
- }
-
- VolatileImageGraphics(VolatileImageGraphics copyFrom)
- {
- super( copyFrom.owner.offScreen );
- owner = copyFrom.owner;
+ this.owner = img;
+ cairo_t = initFromVolatile( owner.nativePointer, img.width, img.height );
+ setup( cairo_t );
}
- /**
- * Abstract methods.
- */
- public Graphics create()
+ private VolatileImageGraphics(VolatileImageGraphics copy)
{
- return new VolatileImageGraphics( this );
+ this.owner = copy.owner;
+ cairo_t = initFromVolatile(owner.nativePointer, owner.width, owner.height);
+ copy( copy, cairo_t );
}
-
+
public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
{
- surface.copyAreaNative(x, y, width, height, dx, dy, surface.width);
- owner.invalidate();
+ owner.copyArea(x, y, width, height, dx, dy);
}
- /**
- * Overloaded methods that do actual drawing need to enter the gdk threads
- * and also do certain things before and after.
- */
- public void draw(Shape s)
+ public GraphicsConfiguration getDeviceConfiguration()
{
- super.draw(s);
- Rectangle r = s.getBounds();
- owner.invalidate();
+ return owner.component.getGraphicsConfiguration();
}
- public void fill(Shape s)
+ public Graphics create()
{
- super.fill(s);
- Rectangle r = s.getBounds();
- owner.invalidate();
+ return new VolatileImageGraphics( this );
}
- public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer)
{
- super.drawRenderedImage(image, xform);
- owner.invalidate();
+ if( img instanceof GtkVolatileImage )
+ {
+ owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
+ x, y,
+ ((GtkVolatileImage)img).width,
+ ((GtkVolatileImage)img).height );
+ return true;
+ }
+ return super.drawImage( img, x, y, observer );
}
-
- protected boolean drawImage(Image img, AffineTransform xform,
- Color bgcolor, ImageObserver obs)
+
+ public boolean drawImage(Image img, int x, int y, int width, int height,
+ ImageObserver observer)
{
- boolean rv = super.drawImage(img, xform, bgcolor, obs);
- owner.invalidate();
- return rv;
+ if( img instanceof GtkVolatileImage )
+ {
+ owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
+ x, y, width, height );
+ return true;
+ }
+ return super.drawImage( img, x, y, width, height, observer );
}
- public void drawGlyphVector(GlyphVector gv, float x, float y)
+ protected Rectangle2D getRealBounds()
{
- super.drawGlyphVector(gv, x, y);
- owner.invalidate();
+ return new Rectangle2D.Double(0, 0, owner.width, owner.height);
}
}
diff --git a/gnu/java/awt/peer/qt/QtGraphics.java b/gnu/java/awt/peer/qt/QtGraphics.java
index f9b4f2672..7b828f7e9 100644
--- a/gnu/java/awt/peer/qt/QtGraphics.java
+++ b/gnu/java/awt/peer/qt/QtGraphics.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
import java.awt.AlphaComposite;
+import java.awt.AWTPermission;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
@@ -605,8 +606,16 @@ public abstract class QtGraphics extends Graphics2D
composite = comp;
}
else
- throw new UnsupportedOperationException("We don't support custom"+
- " composites yet.");
+ {
+ // FIXME: this check is only required "if this Graphics2D
+ // context is drawing to a Component on the display screen".
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AWTPermission("readDisplayPixels"));
+
+ throw new UnsupportedOperationException("We don't support custom"+
+ " composites yet.");
+ }
}
public Composite getComposite()
diff --git a/gnu/java/awt/peer/qt/QtToolkit.java b/gnu/java/awt/peer/qt/QtToolkit.java
index 591b52803..a8bfb1b51 100644
--- a/gnu/java/awt/peer/qt/QtToolkit.java
+++ b/gnu/java/awt/peer/qt/QtToolkit.java
@@ -41,7 +41,6 @@ import gnu.classpath.Configuration;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
-import gnu.java.awt.peer.ClasspathTextLayoutPeer;
import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.Button;
@@ -136,8 +135,7 @@ public class QtToolkit extends ClasspathToolkit
{
eventQueue = new EventQueue();
repaintThread = new QtRepaintThread();
- if (Configuration.INIT_LOAD_LIBRARY)
- System.loadLibrary("qtpeer");
+ System.loadLibrary("qtpeer");
String theme = null;
try
@@ -403,6 +401,11 @@ public class QtToolkit extends ClasspathToolkit
String jobtitle,
Properties props)
{
+ SecurityManager sm;
+ sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPrintJobAccess();
+
throw new RuntimeException("Not implemented");
}
@@ -446,12 +449,6 @@ public class QtToolkit extends ClasspathToolkit
return new QtFontPeer (name, attrs);
}
- public ClasspathTextLayoutPeer getClasspathTextLayoutPeer(AttributedString str,
- FontRenderContext frc)
- {
- return null;
- }
-
// FIXME
public Font createFont(int format, InputStream stream)
{
diff --git a/gnu/java/awt/peer/swing/SwingComponentPeer.java b/gnu/java/awt/peer/swing/SwingComponentPeer.java
index f60c8e96c..96ccc00b8 100644
--- a/gnu/java/awt/peer/swing/SwingComponentPeer.java
+++ b/gnu/java/awt/peer/swing/SwingComponentPeer.java
@@ -48,8 +48,6 @@ import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
-import java.awt.GraphicsDevice;
-import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
@@ -101,8 +99,8 @@ public class SwingComponentPeer
/**
* Creates a SwingComponentPeer instance. Subclasses are expected to call
* this constructor and thereafter call
- * {@link #init(Component, SwingComponent)} in order to setup the AWT and
- * Swing components properly.
+ * {@link #init(Component,SwingComponent)}
+ * in order to setup the AWT and Swing components properly.
*/
protected SwingComponentPeer()
{
@@ -167,12 +165,9 @@ public class SwingComponentPeer
*/
public Image createImage(int width, int height)
{
- GraphicsEnvironment graphicsEnv =
- GraphicsEnvironment.getLocalGraphicsEnvironment();
- GraphicsDevice dev = graphicsEnv.getDefaultScreenDevice();
- GraphicsConfiguration conf = dev.getDefaultConfiguration();
- Image image = conf.createCompatibleImage(width, height);
- return image;
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.createImage(width, height);
}
/**
@@ -336,21 +331,24 @@ public class SwingComponentPeer
{
case PaintEvent.UPDATE:
case PaintEvent.PAINT:
- Graphics g = getGraphics();
- Rectangle clip = ((PaintEvent)e).getUpdateRect();
- g.clipRect(clip.x, clip.y, clip.width, clip.height);
- //if (this instanceof LightweightPeer)
- // {
+ // This only will work when the component is showing.
+ if (awtComponent.isShowing())
+ {
+ Graphics g = getGraphics();
+ Rectangle clip = ((PaintEvent)e).getUpdateRect();
+ g.clipRect(clip.x, clip.y, clip.width, clip.height);
+ //if (this instanceof LightweightPeer)
+ // {
if (e.getID() == PaintEvent.UPDATE)
awtComponent.update(g);
else
awtComponent.paint(g);
- // }
- // We paint the 'heavyweights' at last, so that they appear on top of
- // everything else.
- peerPaint(g);
-
- g.dispose();
+ // }
+ // We paint the 'heavyweights' at last, so that they appear on top of
+ // everything else.
+ peerPaint(g);
+ g.dispose();
+ }
break;
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
@@ -384,6 +382,11 @@ public class SwingComponentPeer
{
if (swingComponent != null)
swingComponent.getJComponent().setVisible(false);
+
+ Component parent = awtComponent.getParent();
+ if (parent != null)
+ parent.repaint(awtComponent.getX(), awtComponent.getY(),
+ awtComponent.getWidth(), awtComponent.getHeight());
}
/**
@@ -470,17 +473,15 @@ public class SwingComponentPeer
public boolean prepareImage(Image img, int width, int height, ImageObserver ob)
{
Component parent = awtComponent.getParent();
- boolean res;
if(parent != null)
- {
- ComponentPeer parentPeer = parent.getPeer();
- res = parentPeer.prepareImage(img, width, height, ob);
- }
+ {
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.prepareImage(img, width, height, ob);
+ }
else
- {
- res = Toolkit.getDefaultToolkit().prepareImage(img, width, height, ob);
- }
- return res;
+ {
+ return Toolkit.getDefaultToolkit().prepareImage(img, width, height, ob);
+ }
}
public void print(Graphics graphics)
@@ -662,8 +663,10 @@ public class SwingComponentPeer
*/
public void setVisible(boolean visible)
{
- if (swingComponent != null)
- swingComponent.getJComponent().setVisible(visible);
+ if (visible)
+ show();
+ else
+ hide();
}
/**
@@ -782,8 +785,13 @@ public class SwingComponentPeer
public VolatileImage createVolatileImage(int width, int height)
{
Component parent = awtComponent.getParent();
- ComponentPeer parentPeer = parent.getPeer();
- return parentPeer.createVolatileImage(width, height);
+ VolatileImage im = null;
+ if (parent != null)
+ {
+ ComponentPeer parentPeer = parent.getPeer();
+ im = parentPeer.createVolatileImage(width, height);
+ }
+ return im;
}
/**
diff --git a/gnu/java/awt/peer/x/GLGraphics.java b/gnu/java/awt/peer/x/GLGraphics.java
new file mode 100644
index 000000000..c80c85c28
--- /dev/null
+++ b/gnu/java/awt/peer/x/GLGraphics.java
@@ -0,0 +1,123 @@
+/* GLGraphics.java -- Graphics2D impl on top of GLX
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Color;
+import java.awt.GraphicsConfiguration;
+import java.awt.image.ColorModel;
+
+import gnu.java.awt.java2d.AbstractGraphics2D;
+import gnu.x11.extension.glx.GL;
+
+/**
+ * An implementation of Graphics2D on top of the GLX extension of X.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class GLGraphics extends AbstractGraphics2D
+{
+
+ /**
+ * The rendering context.
+ */
+ private GL gl;
+
+ /**
+ * Creates a new GLGraphics that paints on the specified GL context.
+ *
+ * @param g the GL context to paint to
+ */
+ GLGraphics(GL g)
+ {
+ gl = g;
+ }
+
+ public void setBackground(Color b)
+ {
+ super.setBackground(b);
+ gl.clear_color(b.getRed() / 255.F, b.getGreen() / 255.F,
+ b.getBlue() / 255.F, b.getAlpha() / 255.F);
+ }
+
+ public void clearRect(int x, int y, int w, int h)
+ {
+ // TODO: Maybe use fillRect().
+ gl.clear(GL.COLOR_BUFFER_BIT);
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ gl.begin(GL.LINES);
+ gl.vertex2i(x1, y1);
+ gl.vertex2i(x2, y2);
+ gl.end();
+ // TODO: Maybe do:
+ // gl.flush();
+ }
+
+ public void drawRect(int x, int y, int w, int h)
+ {
+ gl.polygon_mode(GL.FRONT_AND_BACK, GL.LINE);
+ gl.begin(GL.POLYGON);
+ gl.recti(x, y, x + w, y + h);
+ gl.end();
+ // TODO: Maybe do:
+ // gl.flush();
+ }
+
+ public void fillRect(int x, int y, int w, int h)
+ {
+ gl.polygon_mode(GL.FRONT_AND_BACK, GL.FILL);
+ gl.recti(x, y, x + w, y + h);
+ // TODO: Maybe do:
+ // gl.flush();
+ }
+
+ protected ColorModel getColorModel()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+}
diff --git a/gnu/java/awt/peer/x/ImageConverter.java b/gnu/java/awt/peer/x/ImageConverter.java
new file mode 100644
index 000000000..6d32448ee
--- /dev/null
+++ b/gnu/java/awt/peer/x/ImageConverter.java
@@ -0,0 +1,113 @@
+/* ImageConverter.java -- Convert arbitrary Image impl to XImage
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageConsumer;
+import java.util.Hashtable;
+
+/**
+ * Convert a non-XImage to an XImage.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class ImageConverter implements ImageConsumer
+{
+
+ private XImage image;
+ private Graphics imageGraphics;
+
+ public void setDimensions(int width, int height)
+ {
+ image = new XImage(width, height);
+ }
+
+ public void setProperties(Hashtable props)
+ {
+ // Ignore for now.
+ }
+
+ public void setColorModel(ColorModel model)
+ {
+ // Ignore for now.
+ }
+
+ public void setHints(int flags)
+ {
+ // Ignore for now.
+ }
+
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int offset, int scansize)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int offset, int scansize)
+ {
+ System.err.println("transferType: " + model.getTransferType());
+ System.err.println("colorModel: " + model);
+ if (imageGraphics == null)
+ imageGraphics = image.getGraphics();
+ int xend = x + w;
+ int yend = y + h;
+ for (int yy = y; yy < yend; yy++)
+ {
+ for (int xx = x; xx < xend; xx++)
+ {
+ int pixel = pixels[yy * scansize + xx + offset];
+ imageGraphics.setColor(new Color(model.getRGB(pixel)));
+ imageGraphics.fillRect(xx, yy, 1, 1);
+ }
+ }
+ }
+
+ public void imageComplete(int status)
+ {
+ // Nothing to do here.
+ }
+
+ XImage getXImage()
+ {
+ return image;
+ }
+}
diff --git a/gnu/java/awt/peer/x/KeyboardMapping.java b/gnu/java/awt/peer/x/KeyboardMapping.java
new file mode 100644
index 000000000..8e0a31f5d
--- /dev/null
+++ b/gnu/java/awt/peer/x/KeyboardMapping.java
@@ -0,0 +1,415 @@
+/* KeyboardMapping.java -- Maps X keysyms to Java keyCode and keyChar
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import gnu.x11.Input;
+import gnu.x11.keysym.Latin1;
+import gnu.x11.keysym.Misc;
+
+import java.awt.event.KeyEvent;
+
+/**
+ * Defines the keyboard mapping from X keysyms to Java
+ * keycodes and keychars.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+final class KeyboardMapping
+{
+
+ /**
+ * Maps X keycodes to AWT keycodes.
+ *
+ * @param xInput the X input event
+ * @param xKeyCode the X keycode to map
+ * @param xMods the X modifiers
+ *
+ * @return the AWT keycode and keychar
+ */
+ static int mapToKeyCode(gnu.x11.Input xInput, int xKeyCode, int xMods)
+ {
+ int mapped = KeyEvent.VK_UNDEFINED;
+ int keysym = xInput.keycode_to_keysym(xKeyCode, xMods, true);
+
+ // Special keys.
+ if (keysym >= 255 << 8)
+ {
+ // FIXME: Add missing mappings.
+ switch (keysym)
+ {
+ case Misc.BACKSPACE:
+ mapped = KeyEvent.VK_BACK_SPACE;
+ break;
+ case Misc.TAB:
+ mapped = KeyEvent.VK_TAB;
+ break;
+ case Misc.CLEAR:
+ mapped = KeyEvent.VK_CLEAR;
+ break;
+ case Misc.RETURN:
+ mapped = KeyEvent.VK_ENTER;
+ break;
+ case Misc.PAUSE:
+ mapped = KeyEvent.VK_PAUSE;
+ break;
+ case Misc.SCROLL_LOCK:
+ mapped = KeyEvent.VK_SCROLL_LOCK;
+ break;
+ case Misc.ESCAPE:
+ mapped = KeyEvent.VK_ESCAPE;
+ break;
+ case Misc.HOME:
+ mapped = KeyEvent.VK_HOME;
+ break;
+ case Misc.LEFT:
+ mapped = KeyEvent.VK_LEFT;
+ break;
+ case Misc.UP:
+ mapped = KeyEvent.VK_UP;
+ break;
+ case Misc.RIGHT:
+ mapped = KeyEvent.VK_RIGHT;
+ break;
+ case Misc.DOWN:
+ mapped = KeyEvent.VK_DOWN;
+ break;
+ case Misc.PAGE_UP:
+ mapped = KeyEvent.VK_PAGE_UP;
+ break;
+ case Misc.PAGE_DOWN:
+ mapped = KeyEvent.VK_PAGE_DOWN;
+ break;
+ case Misc.END:
+ mapped = KeyEvent.VK_END;
+ break;
+ case Misc.BEGIN:
+ mapped = KeyEvent.VK_BEGIN;
+ break;
+ case Misc.INSERT:
+ mapped = KeyEvent.VK_INSERT;
+ break;
+ case Misc.UNDO:
+ mapped = KeyEvent.VK_UNDO;
+ break;
+ case Misc.FIND:
+ mapped = KeyEvent.VK_FIND;
+ break;
+ case Misc.CANCEL:
+ mapped = KeyEvent.VK_CANCEL;
+ break;
+ case Misc.HELP:
+ mapped = KeyEvent.VK_HELP;
+ break;
+ case Misc.MODE_SWITCH:
+ mapped = KeyEvent.VK_MODECHANGE;
+ break;
+ case Misc.NUM_LOCK:
+ mapped = KeyEvent.VK_NUM_LOCK;
+ break;
+ case Misc.KP_LEFT:
+ mapped = KeyEvent.VK_KP_LEFT;
+ break;
+ case Misc.KP_UP:
+ mapped = KeyEvent.VK_KP_UP;
+ break;
+ case Misc.KP_RIGHT:
+ mapped = KeyEvent.VK_KP_RIGHT;
+ break;
+ case Misc.KP_DOWN:
+ mapped = KeyEvent.VK_KP_DOWN;
+ break;
+ case Misc.F1:
+ mapped = KeyEvent.VK_F1;
+ break;
+ case Misc.F2:
+ mapped = KeyEvent.VK_F2;
+ break;
+ case Misc.F3:
+ mapped = KeyEvent.VK_F3;
+ break;
+ case Misc.F4:
+ mapped = KeyEvent.VK_F4;
+ break;
+ case Misc.F5:
+ mapped = KeyEvent.VK_F5;
+ break;
+ case Misc.F6:
+ mapped = KeyEvent.VK_F6;
+ break;
+ case Misc.F7:
+ mapped = KeyEvent.VK_F7;
+ break;
+ case Misc.F8:
+ mapped = KeyEvent.VK_F8;
+ break;
+ case Misc.F9:
+ mapped = KeyEvent.VK_F9;
+ break;
+ case Misc.F10:
+ mapped = KeyEvent.VK_F10;
+ break;
+ case Misc.F11:
+ mapped = KeyEvent.VK_F11;
+ break;
+ case Misc.F12:
+ mapped = KeyEvent.VK_F12;
+ break;
+ case Misc.F13:
+ mapped = KeyEvent.VK_F13;
+ break;
+ case Misc.F14:
+ mapped = KeyEvent.VK_F14;
+ break;
+ case Misc.F15:
+ mapped = KeyEvent.VK_F15;
+ break;
+ case Misc.F16:
+ mapped = KeyEvent.VK_F16;
+ break;
+ case Misc.F17:
+ mapped = KeyEvent.VK_F17;
+ break;
+ case Misc.F18:
+ mapped = KeyEvent.VK_F18;
+ break;
+ case Misc.F19:
+ mapped = KeyEvent.VK_F19;
+ break;
+ case Misc.F20:
+ mapped = KeyEvent.VK_F20;
+ break;
+ case Misc.F21:
+ mapped = KeyEvent.VK_F21;
+ break;
+ case Misc.F22:
+ mapped = KeyEvent.VK_F22;
+ break;
+ case Misc.F23:
+ mapped = KeyEvent.VK_F23;
+ break;
+ case Misc.F24:
+ mapped = KeyEvent.VK_F24;
+ break;
+ case Misc.SHIFT_L:
+ case Misc.SHIFT_R:
+ mapped = KeyEvent.VK_SHIFT;
+ break;
+ case Misc.CONTROL_L:
+ case Misc.CONTROL_R:
+ mapped = KeyEvent.VK_CONTROL;
+ break;
+ case Misc.CAPS_LOCK:
+ case Misc.SHIFT_LOCK:
+ mapped = KeyEvent.VK_CAPS_LOCK;
+ break;
+ case Misc.META_L:
+ case Misc.META_R:
+ mapped = KeyEvent.VK_META;
+ break;
+ case Misc.ALT_L:
+ case Misc.ALT_R:
+ mapped = KeyEvent.VK_ALT;
+ break;
+ case Misc.DELETE:
+ mapped = KeyEvent.VK_DELETE;
+ break;
+ default:
+ mapped = KeyEvent.VK_UNDEFINED;
+ }
+ }
+ // Map Latin1 characters.
+ else if (keysym < 256)
+ {
+ // TODO: Add missing mappings, if any.
+ // Lowercase characters are mapped to
+ // their corresponding upper case pendants.
+ if (keysym >= Latin1.A_SMALL && keysym <= Latin1.Z_SMALL)
+ mapped = keysym - 0x20;
+ // Uppercase characters are mapped 1:1.
+ else if (keysym >= Latin1.A && keysym <= Latin1.Z)
+ mapped = keysym;
+ // Digits are mapped 1:1.
+ else if (keysym >= Latin1.NUM_0 && keysym <= Latin1.NUM_9)
+ mapped = keysym;
+ else
+ {
+ switch (keysym)
+ {
+ case Latin1.SPACE:
+ mapped = KeyEvent.VK_SPACE;
+ break;
+ case Latin1.EXCLAM:
+ mapped = KeyEvent.VK_EXCLAMATION_MARK;
+ break;
+ case Latin1.QUOTE_DBL:
+ mapped = KeyEvent.VK_QUOTEDBL;
+ break;
+ case Latin1.NUMBER_SIGN:
+ mapped = KeyEvent.VK_NUMBER_SIGN;
+ break;
+ case Latin1.DOLLAR:
+ mapped = KeyEvent.VK_DOLLAR;
+ break;
+ case Latin1.AMPERSAND:
+ mapped = KeyEvent.VK_AMPERSAND;
+ break;
+ case Latin1.APOSTROPHE:
+ mapped = KeyEvent.VK_QUOTE;
+ break;
+ case Latin1.PAREN_LEFT:
+ mapped = KeyEvent.VK_LEFT_PARENTHESIS;
+ break;
+ case Latin1.PAREN_RIGHT:
+ mapped = KeyEvent.VK_RIGHT_PARENTHESIS;
+ break;
+ case Latin1.ASTERISK:
+ mapped = KeyEvent.VK_ASTERISK;
+ break;
+ case Latin1.PLUS:
+ mapped = KeyEvent.VK_PLUS;
+ break;
+ case Latin1.COMMA:
+ mapped = KeyEvent.VK_COMMA;
+ break;
+ case Latin1.MINUS:
+ mapped = KeyEvent.VK_MINUS;
+ break;
+ case Latin1.PERIOD:
+ mapped = KeyEvent.VK_PERIOD;
+ break;
+ case Latin1.SLASH:
+ mapped = KeyEvent.VK_SLASH;
+ break;
+ case Latin1.COLON:
+ mapped = KeyEvent.VK_COLON;
+ break;
+ case Latin1.SEMICOLON:
+ mapped = KeyEvent.VK_SEMICOLON;
+ break;
+ case Latin1.LESS:
+ mapped = KeyEvent.VK_LESS;
+ break;
+ case Latin1.EQUAL:
+ mapped = KeyEvent.VK_EQUALS;
+ break;
+ case Latin1.GREATER:
+ mapped = KeyEvent.VK_GREATER;
+ break;
+ case Latin1.AT:
+ mapped = KeyEvent.VK_AT;
+ break;
+ case Latin1.BRACKET_LEFT:
+ mapped = KeyEvent.VK_OPEN_BRACKET;
+ break;
+ case Latin1.BACKSLASH:
+ mapped = KeyEvent.VK_BACK_SLASH;
+ break;
+ case Latin1.BRACKET_RIGHT:
+ mapped = KeyEvent.VK_CLOSE_BRACKET;
+ break;
+ case Latin1.ASCII_CIRCUM:
+ mapped = KeyEvent.VK_CIRCUMFLEX;
+ break;
+ case Latin1.UNDERSCORE:
+ mapped = KeyEvent.VK_UNDERSCORE;
+ break;
+ case Latin1.GRAVE:
+ mapped = KeyEvent.VK_DEAD_GRAVE;
+ break;
+ case Latin1.BRACE_LEFT:
+ mapped = KeyEvent.VK_BRACELEFT;
+ break;
+ case Latin1.BRACE_RIGHT:
+ mapped = KeyEvent.VK_BRACERIGHT;
+ break;
+ case Latin1.ASCII_TILDE:
+ mapped = KeyEvent.VK_DEAD_TILDE;
+ break;
+ case Latin1.EXCLAM_DOWN:
+ mapped = KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+ break;
+ default:
+ mapped = KeyEvent.VK_UNDEFINED;
+ }
+ }
+ }
+ return mapped;
+ }
+
+ /**
+ * Maps X keycodes+modifiers to Java keychars.
+ *
+ * @param xInput The X Input to use for mapping
+ * @param xKeyCode the X keycode
+ * @param xMods the X key modifiers
+ *
+ * @return the Java keychar
+ */
+ static char mapToKeyChar(gnu.x11.Input xInput, int xKeyCode, int xMods)
+ {
+ char mapped = KeyEvent.CHAR_UNDEFINED;
+ char keysym = (char) xInput.keycode_to_keysym(xKeyCode, xMods, false);
+ // FIXME: Map other encodings properly.
+ if (keysym < 256) // Latin1.
+ {
+ mapped = keysym;
+ }
+ return mapped;
+ }
+
+ /**
+ * Maps X modifier masks to AWT modifier masks.
+ *
+ * @param xMods the X modifiers
+ *
+ * @return the AWT modifiers
+ */
+ static int mapModifiers(int xMods)
+ {
+ int mods = 0;
+
+ if ((xMods & Input.SHIFT_MASK) != 0)
+ mods |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
+ if ((xMods & Input.ALT_MASK) != 0)
+ mods |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
+ if ((xMods & Input.CONTROL_MASK) != 0)
+ mods |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
+
+ return mods;
+ }
+}
diff --git a/gnu/java/awt/peer/x/XEventPump.java b/gnu/java/awt/peer/x/XEventPump.java
new file mode 100644
index 000000000..bd1ef08ce
--- /dev/null
+++ b/gnu/java/awt/peer/x/XEventPump.java
@@ -0,0 +1,287 @@
+/* XEventPump.java -- Pumps events from X to AWT
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.PaintEvent;
+import java.util.HashMap;
+
+import gnu.x11.Display;
+import gnu.x11.event.ButtonPress;
+import gnu.x11.event.ButtonRelease;
+import gnu.x11.event.ConfigureNotify;
+import gnu.x11.event.Event;
+import gnu.x11.event.Expose;
+import gnu.x11.event.Input;
+import gnu.x11.event.KeyPress;
+import gnu.x11.event.KeyRelease;
+import gnu.x11.event.MotionNotify;
+
+/**
+ * Fetches events from X, translates them to AWT events and pumps them up
+ * into the AWT event queue.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XEventPump
+ implements Runnable
+{
+
+ /**
+ * The X Display from which we fetch and pump up events.
+ */
+ private Display display;
+
+ /**
+ * Maps X Windows to AWT Windows to be able to correctly determine the
+ * event targets.
+ */
+ private HashMap windows;
+
+ /**
+ * Indicates if we are currently inside a drag operation. This is
+ * set to the button ID when a button is pressed and to -1 (indicating
+ * that no drag is active) when the mouse is released.
+ */
+ private int drag;
+
+ /**
+ * Creates a new XEventPump for the specified X Display.
+ *
+ * @param d the X Display
+ */
+ XEventPump(Display d)
+ {
+ display = d;
+ windows = new HashMap();
+ drag = -1;
+ Thread t = new Thread(this);
+ t.start();
+ }
+
+ /**
+ * The main event pump loop. This basically fetches events from the
+ * X Display and pumps them into the system event queue.
+ */
+ public void run()
+ {
+ while (display.connected)
+ {
+ try
+ {
+ Event xEvent = display.next_event();
+ handleEvent(xEvent);
+ }
+ catch (ThreadDeath death)
+ {
+ // If someone wants to kill us, let them.
+ return;
+ }
+ catch (Throwable x)
+ {
+ System.err.println("Exception during event dispatch:");
+ x.printStackTrace(System.err);
+ }
+ }
+ }
+
+ /**
+ * Adds an X Window to AWT Window mapping. This is required so that the
+ * event pump can correctly determine the event targets.
+ *
+ * @param xWindow the X Window
+ * @param awtWindow the AWT Window
+ */
+ void registerWindow(gnu.x11.Window xWindow, Window awtWindow)
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("registering window id: " + xWindow.id);
+ windows.put(new Integer(xWindow.id), awtWindow);
+ }
+
+ void unregisterWindow(gnu.x11.Window xWindow)
+ {
+ windows.remove(new Integer(xWindow.id));
+ }
+
+ private void handleEvent(Event xEvent)
+ {
+ Integer key = new Integer(xEvent.window_id());;
+ Window awtWindow = (Window) windows.get(key);
+
+ if (XToolkit.DEBUG)
+ System.err.println("fetched event: " + xEvent);
+ switch (xEvent.code())
+ {
+ case ButtonPress.CODE:
+ ButtonPress bp = (ButtonPress) xEvent;
+ // Create and post the mouse event.
+ int button = bp.detail();
+ drag = button;
+ MouseEvent mp = new MouseEvent(awtWindow, MouseEvent.MOUSE_PRESSED,
+ System.currentTimeMillis(), 0,
+ bp.event_x(), bp.event_y(),
+ 1, false, button);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mp);
+ break;
+ case ButtonRelease.CODE:
+ ButtonRelease br = (ButtonRelease) xEvent;
+ drag = -1;
+ MouseEvent mr = new MouseEvent(awtWindow, MouseEvent.MOUSE_RELEASED,
+ System.currentTimeMillis(), 0,
+ br.event_x(), br.event_y(),
+ 1, false, br.detail());
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mr);
+ break;
+ case MotionNotify.CODE:
+ MotionNotify mn = (MotionNotify) xEvent;
+ MouseEvent mm;
+ if (drag == -1)
+ {
+ mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_MOVED,
+ System.currentTimeMillis(), 0,
+ mn.event_x(), mn.event_y(),
+ 1, false);
+ }
+ else
+ {
+ mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_DRAGGED,
+ System.currentTimeMillis(), 0,
+ mn.event_x(), mn.event_y(),
+ 1, false);
+ }
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mm);
+ break;
+ case ConfigureNotify.CODE:
+ ConfigureNotify c = (ConfigureNotify) xEvent;
+ if (XToolkit.DEBUG)
+ System.err.println("resize request for window id: " + key);
+
+ // Detect and report size changes.
+ if (c.width() != awtWindow.getWidth()
+ || c.height() != awtWindow.getHeight())
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("Setting size on AWT window: " + c.width()
+ + ", " + c.height() + ", " + awtWindow.getWidth()
+ + ", " + awtWindow.getHeight());
+ ((XFramePeer) awtWindow.getPeer()).callback = true;
+ awtWindow.setSize(c.width(), c.height());
+ ((XFramePeer) awtWindow.getPeer()).callback = false;
+ }
+ break;
+ case Expose.CODE:
+ Expose exp = (Expose) xEvent;
+ if (XToolkit.DEBUG)
+ System.err.println("expose request for window id: " + key);
+ Rectangle r = new Rectangle(exp.x(), exp.y(), exp.width(),
+ exp.height());
+ //System.err.println("expose paint: " + r);
+ // We need to clear the background of the exposed rectangle.
+ Graphics g = awtWindow.getGraphics();
+ g.clearRect(r.x, r.y, r.width, r.height);
+ g.dispose();
+ PaintEvent pev = new PaintEvent(awtWindow, PaintEvent.PAINT, r);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(pev);
+ break;
+ case KeyPress.CODE:
+ case KeyRelease.CODE:
+ handleKeyEvent(xEvent, awtWindow);
+ break;
+ default:
+ if (XToolkit.DEBUG)
+ System.err.println("Unhandled X event: " + xEvent);
+ }
+ }
+
+ /**
+ * Handles key events from X.
+ *
+ * @param xEvent the X event
+ * @param awtWindow the AWT window to which the event gets posted
+ */
+ private void handleKeyEvent(Event xEvent, Window awtWindow)
+ {
+ Input keyEvent = (Input) xEvent;
+ int xKeyCode = keyEvent.detail();
+ int xMods = keyEvent.state();
+ int keyCode = KeyboardMapping.mapToKeyCode(xEvent.display.input, xKeyCode,
+ xMods);
+ char keyChar = KeyboardMapping.mapToKeyChar(xEvent.display.input, xKeyCode,
+ xMods);
+ if (XToolkit.DEBUG)
+ System.err.println("XEventPump.handleKeyEvent: " + xKeyCode + ", "
+ + xMods + ": " + ((int) keyChar) + ", " + keyCode);
+ int awtMods = KeyboardMapping.mapModifiers(xMods);
+ long when = System.currentTimeMillis();
+ KeyEvent ke;
+ if (keyEvent.code() == KeyPress.CODE)
+ {
+ ke = new KeyEvent(awtWindow, KeyEvent.KEY_PRESSED, when,
+ awtMods, keyCode,
+ KeyEvent.CHAR_UNDEFINED);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
+ if (keyChar != KeyEvent.CHAR_UNDEFINED)
+ {
+ ke = new KeyEvent(awtWindow, KeyEvent.KEY_TYPED, when,
+ awtMods, KeyEvent.VK_UNDEFINED,
+ keyChar);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
+ }
+
+ }
+ else
+ {
+ ke = new KeyEvent(awtWindow, KeyEvent.KEY_RELEASED, when,
+ awtMods, keyCode,
+ KeyEvent.CHAR_UNDEFINED);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
+ }
+
+ }
+
+
+}
+
diff --git a/gnu/java/awt/peer/x/XFontPeer.java b/gnu/java/awt/peer/x/XFontPeer.java
new file mode 100644
index 000000000..8a499db1a
--- /dev/null
+++ b/gnu/java/awt/peer/x/XFontPeer.java
@@ -0,0 +1,740 @@
+/* XFontPeer.java -- The font peer for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.AWTError;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.CharacterIterator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.x11.Display;
+import gnu.x11.Fontable;
+
+/**
+ * The bridge from AWT to X fonts.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XFontPeer
+ extends ClasspathFontPeer
+{
+
+ /**
+ * The font mapping as specified in the file fonts.properties.
+ */
+ private static Properties fontProperties;
+ static
+ {
+ fontProperties = new Properties();
+ InputStream in = XFontPeer.class.getResourceAsStream("fonts.properties");
+ try
+ {
+ fontProperties.load(in);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * The FontMetrics implementation for XFontPeer.
+ */
+ private class XFontMetrics
+ extends FontMetrics
+ {
+ /**
+ * The ascent of the font.
+ */
+ int ascent;
+
+ /**
+ * The descent of the font.
+ */
+ int descent;
+
+ /**
+ * The maximum of the character advances.
+ */
+ private int maxAdvance;
+
+ /**
+ * The internal leading.
+ */
+ int leading;
+
+ /**
+ * Cached string metrics. This caches string metrics locally so that the
+ * server doesn't have to be asked each time.
+ */
+ private HashMap metricsCache;
+
+ /**
+ * The widths of the characters indexed by the characters themselves.
+ */
+ private int[] charWidths;
+
+ /**
+ * Creates a new XFontMetrics for the specified font.
+ *
+ * @param font the font
+ */
+ protected XFontMetrics(Font font)
+ {
+ super(font);
+ metricsCache = new HashMap();
+ Fontable.FontReply info = getXFont().info();
+ ascent = info.font_ascent();
+ descent = info.font_descent();
+ maxAdvance = info.max_bounds().character_width();
+ leading = 0; // TODO: Not provided by X. Possible not needed.
+
+ if (info.min_byte1() == 0 && info.max_byte1() == 0)
+ readCharWidthsLinear(info);
+ else
+ readCharWidthsNonLinear(info);
+ }
+
+ /**
+ * Reads the character widths when specified in a linear fashion. That is
+ * when the min-byte1 and max-byte2 fields are both zero in the X protocol.
+ *
+ * @param info the font info reply
+ */
+ private void readCharWidthsLinear(Fontable.FontReply info)
+ {
+ int startIndex = info.min_char_or_byte2();
+ int endIndex = info.max_char_or_byte2();
+ charWidths = new int[endIndex + 1];
+ // All the characters before startIndex are zero width.
+ for (int i = 0; i < startIndex; i++)
+ {
+ charWidths[i] = 0;
+ }
+ // All the other character info is fetched from the font info.
+ int index = startIndex;
+ Iterator charInfos = info.char_infos().iterator();
+ while (charInfos.hasNext())
+ {
+ Fontable.FontReply.CharInfo charInfo =
+ (Fontable.FontReply.CharInfo) charInfos.next();
+ charWidths[index] = charInfo.character_width();
+ index++;
+ }
+ }
+
+ private void readCharWidthsNonLinear(Fontable.FontReply info)
+ {
+ // TODO: Implement.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /**
+ * Returns the ascent of the font.
+ *
+ * @return the ascent of the font
+ */
+ public int getAscent()
+ {
+ return ascent;
+ }
+
+ /**
+ * Returns the descent of the font.
+ *
+ * @return the descent of the font
+ */
+ public int getDescent()
+ {
+ return descent;
+ }
+
+ /**
+ * Returns the overall height of the font. This is the distance from
+ * baseline to baseline (usually ascent + descent + leading).
+ *
+ * @return the overall height of the font
+ */
+ public int getHeight()
+ {
+ return ascent + descent;
+ }
+
+ /**
+ * Returns the leading of the font.
+ *
+ * @return the leading of the font
+ */
+ public int getLeading()
+ {
+ return leading;
+ }
+
+ /**
+ * Returns the maximum advance for this font.
+ *
+ * @return the maximum advance for this font
+ */
+ public int getMaxAdvance()
+ {
+ return maxAdvance;
+ }
+
+ /**
+ * Determines the width of the specified character <code>c</code>.
+ *
+ * @param c the character
+ *
+ * @return the width of the character
+ */
+ public int charWidth(char c)
+ {
+ int width;
+ if (c > charWidths.length)
+ width = charWidths['?'];
+ else
+ width = charWidths[c];
+ return width;
+ }
+
+ /**
+ * Determines the overall width of the specified string.
+ *
+ * @param c the char buffer holding the string
+ * @param offset the starting offset of the string in the buffer
+ * @param length the number of characters in the string buffer
+ *
+ * @return the overall width of the specified string
+ */
+ public int charsWidth(char[] c, int offset, int length)
+ {
+ int width = 0;
+ if (c.length > 0 && length > 0)
+ {
+ String s = new String(c, offset, length);
+ width = stringWidth(s);
+ }
+ return width;
+ }
+
+ /**
+ * Determines the overall width of the specified string.
+ *
+ * @param s the string
+ *
+ * @return the overall width of the specified string
+ */
+ public int stringWidth(String s)
+ {
+ int width = 0;
+ if (s.length() > 0)
+ {
+ if (metricsCache.containsKey(s))
+ {
+ width = ((Integer) metricsCache.get(s)).intValue();
+ }
+ else
+ {
+ Fontable.TextExtentReply extents = getXFont().text_extent(s);
+ /*
+ System.err.println("string: '" + s + "' : ");
+ System.err.println("ascent: " + extents.getAscent());
+ System.err.println("descent: " + extents.getDescent());
+ System.err.println("overall ascent: " + extents.getOverallAscent());
+ System.err.println("overall descent: " + extents.getOverallDescent());
+ System.err.println("overall width: " + extents.getOverallWidth());
+ System.err.println("overall left: " + extents.getOverallLeft());
+ System.err.println("overall right: " + extents.getOverallRight());
+ */
+ width = extents.overall_width(); // + extents.overall_left();
+ //System.err.println("String: " + s + ", width: " + width);
+ metricsCache.put(s, new Integer(width));
+ }
+ }
+ //System.err.print("stringWidth: '" + s + "': ");
+ //System.err.println(width);
+ return width;
+ }
+ }
+
+ /**
+ * The LineMetrics implementation for the XFontPeer.
+ */
+ private class XLineMetrics
+ extends LineMetrics
+ {
+
+ /**
+ * Returns the ascent of the font.
+ *
+ * @return the ascent of the font
+ */
+ public float getAscent()
+ {
+ return fontMetrics.ascent;
+ }
+
+ public int getBaselineIndex()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException();
+ }
+
+ public float[] getBaselineOffsets()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the descent of the font.
+ *
+ * @return the descent of the font
+ */
+ public float getDescent()
+ {
+ return fontMetrics.descent;
+ }
+
+ /**
+ * Returns the overall height of the font. This is the distance from
+ * baseline to baseline (usually ascent + descent + leading).
+ *
+ * @return the overall height of the font
+ */
+ public float getHeight()
+ {
+ return fontMetrics.ascent + fontMetrics.descent;
+ }
+
+ /**
+ * Returns the leading of the font.
+ *
+ * @return the leading of the font
+ */
+ public float getLeading()
+ {
+ return fontMetrics.leading;
+ }
+
+ public int getNumChars()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException();
+ }
+
+ public float getStrikethroughOffset()
+ {
+ return 0.F; // TODO: Provided by X??
+ }
+
+ public float getStrikethroughThickness()
+ {
+ return 1.F; // TODO: Provided by X??
+ }
+
+ public float getUnderlineOffset()
+ {
+ return 0.F; // TODO: Provided by X??
+ }
+
+ public float getUnderlineThickness()
+ {
+ return 1.F; // TODO: Provided by X??
+ }
+
+ }
+
+ /**
+ * The X font.
+ */
+ private gnu.x11.Font xfont;
+
+ private String name;
+
+ private int style;
+
+ private int size;
+
+ /**
+ * The font metrics for this font.
+ */
+ XFontMetrics fontMetrics;
+
+ /**
+ * Creates a new XFontPeer for the specified font name, style and size.
+ *
+ * @param name the font name
+ * @param style the font style (bold / italic / normal)
+ * @param size the size of the font
+ */
+ public XFontPeer(String name, int style, int size)
+ {
+ super(name, style, size);
+ this.name = name;
+ this.style = style;
+ this.size = size;
+ }
+
+ /**
+ * Creates a new XFontPeer for the specified font name and style
+ * attributes.
+ *
+ * @param name the font name
+ * @param atts the font attributes
+ */
+ public XFontPeer(String name, Map atts)
+ {
+ super(name, atts);
+ String family = name;
+ if (family == null || family.equals(""))
+ family = (String) atts.get(TextAttribute.FAMILY);
+ if (family == null)
+ family = "SansSerif";
+
+ int size = 12;
+ Float sizeFl = (Float) atts.get(TextAttribute.SIZE);
+ if (sizeFl != null)
+ size = sizeFl.intValue();
+
+ int style = 0;
+ // Detect italic attribute.
+ Float posture = (Float) atts.get(TextAttribute.POSTURE);
+ if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR))
+ style |= Font.ITALIC;
+
+ // Detect bold attribute.
+ Float weight = (Float) atts.get(TextAttribute.WEIGHT);
+ if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0)
+ style |= Font.BOLD;
+
+ this.name = name;
+ this.style = style;
+ this.size = size;
+ }
+
+ /**
+ * Initializes the font peer with the specified attributes. This method is
+ * called from both constructors.
+ *
+ * @param name the font name
+ * @param style the font style
+ * @param size the font size
+ */
+ private void init(String name, int style, int size)
+ {
+ GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice dev = env.getDefaultScreenDevice();
+ if (dev instanceof XGraphicsDevice)
+ {
+ Display display = ((XGraphicsDevice) dev).getDisplay();
+ String fontDescr = encodeFont(name, style, size);
+ if (XToolkit.DEBUG)
+ System.err.println("XLFD font description: " + fontDescr);
+ xfont = new gnu.x11.Font(display, fontDescr);
+ }
+ else
+ {
+ throw new AWTError("Local GraphicsEnvironment is not XWindowGraphicsEnvironment");
+ }
+ }
+
+ public boolean canDisplay(Font font, char c)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String getSubFamilyName(Font font, Locale locale)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String getPostScriptName(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getNumGlyphs(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getMissingGlyphCode(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public byte getBaselineFor(Font font, char c)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String getGlyphName(Font font, int glyphIndex)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GlyphVector createGlyphVector(Font font, FontRenderContext frc,
+ CharacterIterator ci)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GlyphVector createGlyphVector(Font font, FontRenderContext ctx,
+ int[] glyphCodes)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc,
+ char[] chars, int start, int limit,
+ int flags)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns the font metrics for the specified font.
+ *
+ * @param font the font for which to fetch the font metrics
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ if (font.getPeer() != this)
+ throw new AWTError("The specified font has a different peer than this");
+
+ if (fontMetrics == null)
+ fontMetrics = new XFontMetrics(font);
+ return fontMetrics;
+ }
+
+ /**
+ * Frees the font in the X server.
+ */
+ protected void finalize()
+ {
+ if (xfont != null)
+ xfont.close();
+ }
+
+ public boolean hasUniformLineMetrics(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns the line metrics for this font and the specified string and
+ * font render context.
+ */
+ public LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin,
+ int limit, FontRenderContext rc)
+ {
+ return new XLineMetrics();
+ }
+
+ public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Rectangle2D getStringBounds(Font font, CharacterIterator ci,
+ int begin, int limit, FontRenderContext frc)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Encodes a font name + style + size specification into a X logical font
+ * description (XLFD) as described here:
+ *
+ * http://www.meretrx.com/e93/docs/xlfd.html
+ *
+ * This is implemented to look up the font description in the
+ * fonts.properties of this package.
+ *
+ * @param name the font name
+ * @param atts the text attributes
+ *
+ * @return the encoded font description
+ */
+ static String encodeFont(String name, Map atts)
+ {
+ String family = name;
+ if (family == null || family.equals(""))
+ family = (String) atts.get(TextAttribute.FAMILY);
+ if (family == null)
+ family = "SansSerif";
+
+ int size = 12;
+ Float sizeFl = (Float) atts.get(TextAttribute.SIZE);
+ if (sizeFl != null)
+ size = sizeFl.intValue();
+
+ int style = 0;
+ // Detect italic attribute.
+ Float posture = (Float) atts.get(TextAttribute.POSTURE);
+ if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR))
+ style |= Font.ITALIC;
+
+ // Detect bold attribute.
+ Float weight = (Float) atts.get(TextAttribute.WEIGHT);
+ if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0)
+ style |= Font.BOLD;
+
+ return encodeFont(name, style, size);
+ }
+
+ /**
+ * Encodes a font name + style + size specification into a X logical font
+ * description (XLFD) as described here:
+ *
+ * http://www.meretrx.com/e93/docs/xlfd.html
+ *
+ * This is implemented to look up the font description in the
+ * fonts.properties of this package.
+ *
+ * @param name the font name
+ * @param style the font style
+ * @param size the font size
+ *
+ * @return the encoded font description
+ */
+ static String encodeFont(String name, int style, int size)
+ {
+ StringBuilder key = new StringBuilder();
+ key.append(validName(name));
+ key.append('.');
+ switch (style)
+ {
+ case Font.BOLD:
+ key.append("bold");
+ break;
+ case Font.ITALIC:
+ key.append("italic");
+ break;
+ case (Font.BOLD | Font.ITALIC):
+ key.append("bolditalic");
+ break;
+ case Font.PLAIN:
+ default:
+ key.append("plain");
+
+ }
+
+ String protoType = fontProperties.getProperty(key.toString());
+ return protoType.replaceFirst("%d", String.valueOf(size));
+ }
+
+ /**
+ * Checks the specified font name for a valid font name. If the font name
+ * is not known, then this returns 'sansserif' as fallback.
+ *
+ * @param name the font name to check
+ *
+ * @return a valid font name
+ */
+ static String validName(String name)
+ {
+ String retVal;
+ if (name.equalsIgnoreCase("sansserif")
+ || name.equalsIgnoreCase("serif")
+ || name.equalsIgnoreCase("monospaced")
+ || name.equalsIgnoreCase("dialog")
+ || name.equalsIgnoreCase("dialoginput"))
+ {
+ retVal = name.toLowerCase();
+ }
+ else
+ {
+ retVal = "sansserif";
+ }
+ return retVal;
+ }
+
+ /**
+ * Returns the X Font reference. This lazily loads the font when first
+ * requested.
+ *
+ * @return the X Font reference
+ */
+ gnu.x11.Font getXFont()
+ {
+ if (xfont == null)
+ {
+ init(name, style, size);
+ }
+ return xfont;
+ }
+}
diff --git a/gnu/java/awt/peer/x/XFontPeer2.java b/gnu/java/awt/peer/x/XFontPeer2.java
new file mode 100644
index 000000000..25371de1a
--- /dev/null
+++ b/gnu/java/awt/peer/x/XFontPeer2.java
@@ -0,0 +1,335 @@
+/* XFontPeer2.java -- A Java based TTF font peer for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.File;
+import java.io.FileInputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Locale;
+import java.util.Map;
+
+import gnu.java.awt.font.FontDelegate;
+import gnu.java.awt.font.FontFactory;
+import gnu.java.awt.peer.ClasspathFontPeer;
+
+public class XFontPeer2
+ extends ClasspathFontPeer
+{
+
+ private class XLineMetrics
+ extends LineMetrics
+ {
+
+ private Font font;
+// private CharacterIterator characterIterator;
+// private int begin;
+// private int limit;
+ private FontRenderContext fontRenderContext;
+ XLineMetrics(Font f, CharacterIterator ci, int b, int l,
+ FontRenderContext rc)
+ {
+ font = f;
+// characterIterator = ci;
+// begin = b;
+// limit = l;
+ fontRenderContext = rc;
+ }
+
+ public float getAscent()
+ {
+ return fontDelegate.getAscent(font.getSize(), fontRenderContext.getTransform(),
+ fontRenderContext.isAntiAliased(),
+ fontRenderContext.usesFractionalMetrics(), true);
+ }
+
+ public int getBaselineIndex()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public float[] getBaselineOffsets()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public float getDescent()
+ {
+ return (int) fontDelegate.getDescent(font.getSize(),
+ new AffineTransform(), false, false,
+ false);
+ }
+
+ public float getHeight()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public float getLeading()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public int getNumChars()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public float getStrikethroughOffset()
+ {
+ return 0.F;
+ }
+
+ public float getStrikethroughThickness()
+ {
+ return 0.F;
+ }
+
+ public float getUnderlineOffset()
+ {
+ return 0.F;
+ }
+
+ public float getUnderlineThickness()
+ {
+ return 0.F;
+ }
+
+ }
+
+ private class XFontMetrics
+ extends FontMetrics
+ {
+ XFontMetrics(Font f)
+ {
+ super(f);
+ }
+
+ public int getAscent()
+ {
+ return (int) fontDelegate.getAscent(getFont().getSize(),
+ new AffineTransform(), false, false,
+ false);
+ }
+
+ public int getDescent()
+ {
+ return (int) fontDelegate.getDescent(getFont().getSize(),
+ new AffineTransform(), false, false,
+ false);
+ }
+
+ public int getHeight()
+ {
+ GlyphVector gv = fontDelegate.createGlyphVector(getFont(),
+ new FontRenderContext(new AffineTransform(), false, false),
+ new StringCharacterIterator("m"));
+ Rectangle2D b = gv.getVisualBounds();
+ return (int) b.getHeight();
+ }
+
+ public int charWidth(char c)
+ {
+ Point2D advance = new Point2D.Double();
+ fontDelegate.getAdvance(c, getFont().getSize(), new AffineTransform(),
+ false, false, true, advance);
+ return (int) advance.getX();
+ }
+
+ public int charsWidth(char[] chars, int offs, int len)
+ {
+ return stringWidth(new String(chars, offs, len));
+ }
+
+ public int stringWidth(String s)
+ {
+ GlyphVector gv = fontDelegate.createGlyphVector(getFont(),
+ new FontRenderContext(new AffineTransform(), false, false),
+ new StringCharacterIterator(s));
+ Rectangle2D b = gv.getVisualBounds();
+ return (int) b.getWidth();
+ }
+ }
+
+ private FontDelegate fontDelegate;
+
+ XFontPeer2(String name, int style, int size)
+ {
+ super(name, style, size);
+ try
+ {
+ File fontfile = new File("/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf");
+ FileInputStream in = new FileInputStream(fontfile);
+ FileChannel ch = in.getChannel();
+ ByteBuffer buffer = ch.map(FileChannel.MapMode.READ_ONLY, 0,
+ fontfile.length());
+ fontDelegate = FontFactory.createFonts(buffer)[0];
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ XFontPeer2(String name, Map atts)
+ {
+ super(name, atts);
+ try
+ {
+ File fontfile = new File("/usr/share/fonts/truetype/freefont/FreeSans.ttf");
+ FileInputStream in = new FileInputStream(fontfile);
+ FileChannel ch = in.getChannel();
+ ByteBuffer buffer = ch.map(FileChannel.MapMode.READ_ONLY, 0,
+ fontfile.length());
+ fontDelegate = FontFactory.createFonts(buffer)[0];
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ public boolean canDisplay(Font font, char c)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public String getSubFamilyName(Font font, Locale locale)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public String getPostScriptName(Font font)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public int getNumGlyphs(Font font)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public int getMissingGlyphCode(Font font)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public byte getBaselineFor(Font font, char c)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public String getGlyphName(Font font, int glyphIndex)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public GlyphVector createGlyphVector(Font font, FontRenderContext frc, CharacterIterator ci)
+ {
+ return fontDelegate.createGlyphVector(font, frc, ci);
+ }
+
+ public GlyphVector createGlyphVector(Font font, FontRenderContext ctx, int[] glyphCodes)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc, char[] chars, int start, int limit, int flags)
+ {
+ StringCharacterIterator i = new StringCharacterIterator(new String(chars), start, limit, 0);
+ return fontDelegate.createGlyphVector(font, frc, i);
+ }
+
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return new XFontMetrics(font);
+ }
+
+ public boolean hasUniformLineMetrics(Font font)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin, int limit, FontRenderContext rc)
+ {
+ return new XLineMetrics(font, ci, begin, limit, rc);
+ }
+
+ public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public Rectangle2D getStringBounds(Font font, CharacterIterator ci, int begin, int limit, FontRenderContext frc)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+}
diff --git a/gnu/java/awt/peer/x/XFramePeer.java b/gnu/java/awt/peer/x/XFramePeer.java
new file mode 100644
index 000000000..1d34b1a81
--- /dev/null
+++ b/gnu/java/awt/peer/x/XFramePeer.java
@@ -0,0 +1,321 @@
+/* XFramePeer.java -- The X FramePeer implementation
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+
+import gnu.java.awt.peer.swing.SwingFramePeer;
+import gnu.x11.Window;
+import gnu.x11.event.Event;
+
+public class XFramePeer
+ extends SwingFramePeer
+{
+
+ private static int standardSelect = Event.BUTTON_PRESS_MASK
+ | Event.BUTTON_RELEASE_MASK
+ | Event.POINTER_MOTION_MASK
+ //| Event.RESIZE_REDIRECT_MASK
+ | Event.EXPOSURE_MASK
+ //| Event.PROPERTY_CHANGE_MASK
+ | Event.STRUCTURE_NOTIFY_MASK
+ | Event.KEY_PRESS_MASK
+ | Event.KEY_RELEASE_MASK
+ ;
+
+ /**
+ * The X window.
+ */
+ private Window xwindow;
+
+ /**
+ * Indicates if we are in callback mode, that is when a property (like size)
+ * is changed in reponse to a request from the X server and doesn't need
+ * to be propagated back to the X server.
+ */
+ boolean callback = false;
+
+ public XFramePeer(Frame frame)
+ {
+ super(frame);
+ XGraphicsDevice dev = XToolkit.getDefaultDevice();
+
+ // TODO: Maybe initialize lazily in show().
+ int x = Math.max(frame.getX(), 0);
+ int y = Math.max(frame.getY(), 0);
+ int w = Math.max(frame.getWidth(), 1);
+ int h = Math.max(frame.getHeight(), 1);
+ xwindow = new Window(dev.getDisplay().default_root, x, y, w, h);
+ xwindow.create();
+ xwindow.select_input(standardSelect);
+ dev.getEventPump().registerWindow(xwindow, frame);
+ }
+
+ public void setIconImage(Image image)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setResizable(boolean resizable)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setTitle(String title)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getState()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setState(int state)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setMaximizedBounds(Rectangle r)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setBoundsPrivate(int x, int y, int width, int height)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void toBack()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void toFront()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void updateAlwaysOnTop()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public boolean requestWindowFocus()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Point getLocationOnScreen()
+ {
+ return new Point(xwindow.x, xwindow.y);
+ }
+
+ /**
+ * Returns a XGraphics suitable for drawing on this frame.
+ *
+ * @return a XGraphics suitable for drawing on this frame
+ */
+ public Graphics getGraphics()
+ {
+ return new XGraphics(xwindow);
+ }
+
+ public Image createImage(int w, int h)
+ {
+ return new XImage(w, h);
+ }
+
+ /**
+ * Sets the visibility state of the component. This is called by
+ * {@link Component#setVisible(boolean)}.
+ *
+ * This is implemented to call setVisible() on the Swing component.
+ *
+ * @param visible <code>true</code> to make the component visible,
+ * <code>false</code> to make it invisible
+ */
+ public void setVisible(boolean visible)
+ {
+ if (visible)
+ show();
+ else
+ hide();
+ }
+
+ /**
+ * Makes the component visible. This is called by {@link Component#show()}.
+ *
+ * This is implemented to call setVisible(true) on the Swing component.
+ */
+ public void show()
+ {
+// // Prevent ResizeRedirect events.
+// //xwindow.select_input(noResizeRedirectSelect);
+// Window.Attributes atts = new Window.Attributes();
+// atts.set_override_redirect(true);
+// xwindow.change_attributes(atts);
+
+ // Prevent ResizeRedirect events.
+ //xwindow.select_input(Event.NO_EVENT_MASK);
+ //xwindow.select_input(noResizeRedirectSelect);
+
+ xwindow.map();
+ EventQueue eq = XToolkit.getDefaultToolkit().getSystemEventQueue();
+ java.awt.Window w = (java.awt.Window) super.awtComponent;
+ eq.postEvent(new WindowEvent(w, WindowEvent.WINDOW_OPENED));
+ eq.postEvent(new PaintEvent(w, PaintEvent.PAINT,
+ new Rectangle(0, 0, w.getWidth(),
+ w.getHeight())));
+
+// // Reset input selection.
+// atts.set_override_redirect(false);
+// xwindow.change_attributes(atts);
+ }
+
+ /**
+ * Makes the component invisible. This is called from
+ * {@link Component#hide()}.
+ *
+ * This is implemented to call setVisible(false) on the Swing component.
+ */
+ public void hide()
+ {
+ xwindow.unmap();
+ }
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#reshape(int, int, int, int)}.
+ *
+ * This is implemented to call setBounds() on the Swing component.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+// if (callback)
+// return;
+
+ // Prevent ResizeRedirect events.
+// //xwindow.select_input(noResizeRedirectSelect);
+// Window.Attributes atts = new Window.Attributes();
+// atts.set_override_redirect(true);
+// xwindow.change_attributes(atts);
+
+ // Need to substract insets because AWT size is including insets,
+ // and X size is excuding insets.
+ Insets i = insets();
+ xwindow.move_resize(x - i.left, y - i.right, width - i.left - i.right,
+ height - i.top - i.bottom);
+
+ // Reset input selection.
+// atts = new Window.Attributes();
+// atts.set_override_redirect(false);
+// xwindow.change_attributes(atts);
+ }
+
+ public Insets insets()
+ {
+ Insets i = new Insets(0, 0, 0, 0);
+// Window.GeometryReply g = xwindow.geometry();
+// int b = g.border_width();
+// Insets i = new Insets(b, b, b, b);
+// Window.WMSizeHints wmSize = xwindow.wm_normal_hints();
+// if (wmSize != null)
+// {
+// i.left = wmSize.x() - g.x();
+// i.right = wmSize.width() - g.width() - i.left ;
+// i.top = wmSize.y() - g.y();
+// i.bottom = wmSize.height() - g.height() - i.top;
+// }
+// System.err.println("insets: " + i);
+ return i;
+ }
+
+ /**
+ * Returns the font metrics for the specified font.
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ XFontPeer fontPeer = (XFontPeer) font.getPeer();
+ return fontPeer.getFontMetrics(font);
+ }
+
+ /**
+ * Unregisters the window in the event pump when it is closed.
+ */
+ protected void finalize()
+ {
+ XGraphicsDevice dev = XToolkit.getDefaultDevice();
+ dev.getEventPump().unregisterWindow(xwindow);
+ }
+
+ public Rectangle getBounds()
+ {
+ return new Rectangle(xwindow.x, xwindow.y, xwindow.width, xwindow.height);
+ }
+}
diff --git a/gnu/java/awt/peer/x/XGraphics.java b/gnu/java/awt/peer/x/XGraphics.java
new file mode 100644
index 000000000..81168797c
--- /dev/null
+++ b/gnu/java/awt/peer/x/XGraphics.java
@@ -0,0 +1,855 @@
+/* XGraphics.java -- The Graphics implementation for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import gnu.x11.Drawable;
+import gnu.x11.GC;
+import gnu.x11.Pixmap;
+import gnu.x11.Point;
+
+import java.awt.AWTError;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.RenderingHints.Key;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+public class XGraphics
+ extends Graphics2D
+ implements Cloneable
+{
+
+ /**
+ * The X Drawable to draw on.
+ */
+ private Drawable xdrawable;
+
+ /**
+ * The X graphics context (GC).
+ */
+ private GC xgc;
+
+ /**
+ * The current translation.
+ */
+ private int translateX;
+ private int translateY;
+
+ /**
+ * The current clip. Possibly null.
+ */
+ private Rectangle clip;
+
+ /**
+ * The current font, possibly null.
+ */
+ private Font font;
+
+ /**
+ * The current foreground color, possibly null.
+ */
+ private Color foreground;
+
+ /**
+ * Indicates if this object has been disposed.
+ */
+ private boolean disposed = false;
+
+ /**
+ * Creates a new XGraphics on the specified X Drawable.
+ *
+ * @param d the X Drawable for which we create the Graphics
+ */
+ XGraphics(Drawable d)
+ {
+ xdrawable = d;
+ xgc = new GC(d);
+ translateX = 0;
+ translateY = 0;
+ clip = new Rectangle(0, 0, d.width, d.height);
+ }
+
+ /**
+ * Creates an exact copy of this graphics context.
+ *
+ * @return an exact copy of this graphics context
+ */
+ public Graphics create()
+ {
+ XGraphics copy = (XGraphics) clone();
+ return copy;
+ }
+
+ /**
+ * Translates the origin by (x, y).
+ */
+ public void translate(int x, int y)
+ {
+ translateX += x;
+ translateY += y;
+ if (clip != null)
+ {
+ clip.x -= x;
+ clip.y -= y;
+ setClip(clip);
+ }
+ }
+
+ /**
+ * Returns the current foreground color, possibly <code>null</code>.
+ *
+ * @return the current foreground color, possibly <code>null</code>
+ */
+ public Color getColor()
+ {
+ return foreground;
+ }
+
+ /**
+ * Sets the current foreground color. A <code>null</code> value doesn't
+ * change the current setting.
+ *
+ * @param c the foreground color to set
+ */
+ public void setColor(Color c)
+ {
+ if (c != null)
+ {
+ xgc.set_foreground(c.getRGB());
+ foreground = c;
+ }
+ }
+
+ public void setPaintMode()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setXORMode(Color color)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /**
+ * Returns the current font, possibly <code>null</code>.
+ *
+ * @return the current font, possibly <code>null</code>
+ */
+ public Font getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Sets the font on the graphics context. A <code>null</code> value doesn't
+ * change the current setting.
+ *
+ * @param f the font to set
+ */
+ public void setFont(Font f)
+ {
+ if (f != null)
+ {
+ XFontPeer xFontPeer = (XFontPeer) f.getPeer();
+ xgc.set_font(xFontPeer.getXFont());
+ font = f;
+ }
+ }
+
+ /**
+ * Returns the font metrics for the specified font.
+ *
+ * @param font the font for which we want the font metrics
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ if (font == null)
+ {
+ if (this.font == null)
+ setFont(new Font("Dialog", Font.PLAIN, 12));
+ font = this.font;
+ }
+ XFontPeer xFontPeer = (XFontPeer) font.getPeer();
+ return xFontPeer.getFontMetrics(font);
+ }
+
+ /**
+ * Returns the bounds of the current clip.
+ *
+ * @return the bounds of the current clip
+ */
+ public Rectangle getClipBounds()
+ {
+ return clip != null ? clip.getBounds() : null;
+ }
+
+ /**
+ * Clips the current clip with the specified clip.
+ */
+ public void clipRect(int x, int y, int width, int height)
+ {
+ if (clip == null)
+ {
+ clip = new Rectangle(x, y, width, height);
+ }
+ else
+ {
+ computeIntersection(x, y, width, height, clip);
+ }
+ // Update the X clip setting.
+ setClip(clip.x, clip.y, clip.width, clip.height);
+ }
+
+ /**
+ * Returns <code>true</code> when the specified rectangle intersects with
+ * the current clip, <code>false</code> otherwise. This is overridden to
+ * avoid unnecessary creation of Rectangles via getBounds().
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ *
+ * @return <code>true</code> when the specified rectangle intersects with
+ * the current clip, <code>false</code> otherwise
+ */
+ public boolean hitClip(int x, int y, int w, int h)
+ {
+ boolean hit;
+ if (clip == null)
+ {
+ hit = true;
+ }
+ else
+ {
+ hit = clip.intersects(x, y, w, h);
+ }
+ //System.err.println("hitClip: " + hit);
+ return hit;
+ }
+
+ public void setClip(int x, int y, int width, int height)
+ {
+ if (clip != null)
+ clip.setBounds(x, y, width, height);
+ else
+ clip = new Rectangle(x, y, width, height);
+
+ gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] {
+ new gnu.x11.Rectangle(x, y, width, height) };
+ xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.UN_SORTED);
+ }
+
+ public Shape getClip()
+ {
+ // Return a copy here, so nobody can trash our clip.
+ return clip == null ? null : clip.getBounds();
+ }
+
+ /**
+ * Sets the current clip.
+ *
+ * @param clip the clip to set
+ */
+ public void setClip(Shape clip)
+ {
+ if (clip != null)
+ {
+ Rectangle b;
+ if (clip instanceof Rectangle)
+ {
+ b = (Rectangle) clip;
+ }
+ else
+ {
+ b = clip.getBounds();
+ }
+ setClip(b.x, b.y, b.width, b.height);
+ }
+ else
+ {
+ setClip(0, 0, xdrawable.width, xdrawable.height);
+ }
+ }
+
+ public void copyArea(int x, int y, int width, int height, int dx, int dy)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /**
+ * Draws a line from point (x1, y1) to point (x2, y2).
+ */
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ //System.err.println("drawLine: " + (x1 + translateX) + ", " + ( y1 + translateY) + ", " + (x2 + translateX) + ", " + (y2 + translateY) + " on: " + xdrawable);
+ xdrawable.line(xgc, x1 + translateX, y1 + translateY,
+ x2 + translateX, y2 + translateY);
+ }
+
+ /**
+ * Fills the specified rectangle.
+ */
+ public void fillRect(int x, int y, int width, int height)
+ {
+ xdrawable.rectangle(xgc, x + translateX, y + translateY,
+ width, height, true);
+ }
+
+ public void clearRect(int x, int y, int width, int height)
+ {
+ xgc.set_foreground(Color.WHITE.getRGB());
+ xdrawable.rectangle(xgc, x, y, width, height, true);
+ if (foreground != null)
+ xgc.set_foreground(foreground.getRGB());
+ }
+
+ public void drawRoundRect(int x, int y, int width, int height, int arcWidth,
+ int arcHeight)
+ {
+ // Draw 4 lines.
+ int arcRadiusX = arcWidth / 2;
+ int arcRadiusY = arcHeight / 2;
+ drawLine(x + arcRadiusX, y, x + width - arcRadiusX, y);
+ drawLine(x, y + arcRadiusY, x, y + height - arcRadiusY);
+ drawLine(x + arcRadiusX, y + height, x + width - arcRadiusX, y + height);
+ drawLine(x + width, y + arcRadiusY, x + width, y + height - arcRadiusY);
+
+ // Draw the 4 arcs at the corners.
+ // Upper left.
+ drawArc(x, y, arcWidth, arcHeight, 90, 90);
+ // Lower left.
+ drawArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90);
+ // Upper right.
+ drawArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90);
+ // Lower right.
+ drawArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight,
+ 270, 90);
+ }
+
+ public void fillRoundRect(int x, int y, int width, int height, int arcWidth,
+ int arcHeight)
+ {
+ // Fill the 3 rectangles that make up the inner area.
+ int arcRadiusX = arcWidth / 2;
+ int arcRadiusY = arcHeight / 2;
+ // Left.
+ fillRect(x, y + arcRadiusY, arcRadiusX, height - arcHeight);
+ // Middle.
+ fillRect(x + arcRadiusX, y, width - arcWidth, height);
+ // Right.
+ fillRect(x + width - arcRadiusX, y + arcRadiusY, arcRadiusX,
+ height - arcHeight);
+
+ // Fill the 4 arcs in the corners.
+ // Upper left.
+ fillArc(x, y, arcWidth, arcHeight, 90, 90);
+ // Lower left.
+ fillArc(x, y + height - arcHeight, arcWidth, arcHeight, 180, 90);
+ // Upper right.
+ fillArc(x + width - arcWidth, y, arcWidth, arcHeight, 0, 90);
+ // Lower right.
+ fillArc(x + width - arcWidth, y + height - arcHeight, arcWidth, arcHeight,
+ 270, 90);
+ }
+
+ public void drawOval(int x, int y, int width, int height)
+ {
+ xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, false);
+ }
+
+ public void fillOval(int x, int y, int width, int height)
+ {
+ xdrawable.arc(xgc, x, y, width, height, 0, 360 * 64, true);
+ }
+
+ public void drawArc(int x, int y, int width, int height, int arcStart,
+ int arcAngle)
+ {
+ xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, false);
+ }
+
+ public void fillArc(int x, int y, int width, int height, int arcStart,
+ int arcAngle)
+ {
+ xdrawable.arc(xgc, x, y, width, height, arcStart * 64, arcAngle * 64, true);
+ }
+
+ public void drawPolyline(int[] xPoints, int[] yPoints, int npoints)
+ {
+ int numPoints = Math.min(xPoints.length, yPoints.length);
+ Point[] points = new Point[numPoints];
+ // FIXME: Improve Escher API to accept arrays to avoid creation
+ // of many Point objects.
+ for (int i = 0; i < numPoints; i++)
+ points[i] = new Point(xPoints[i], yPoints[i]);
+ xdrawable.poly_line(xgc, points, Drawable.ORIGIN);
+ }
+
+ public void drawPolygon(int[] xPoints, int[] yPoints, int npoints)
+ {
+ int numPoints = Math.min(xPoints.length, yPoints.length);
+ Point[] points = new Point[numPoints];
+ // FIXME: Improve Escher API to accept arrays to avoid creation
+ // of many Point objects.
+ for (int i = 0; i < numPoints; i++)
+ points[i] = new Point(xPoints[i], yPoints[i]);
+ xdrawable.poly_line(xgc, points, Drawable.ORIGIN);
+ }
+
+ public void fillPolygon(int[] xPoints, int[] yPoints, int npoints)
+ {
+ int numPoints = Math.min(xPoints.length, yPoints.length);
+ Point[] points = new Point[numPoints];
+ // FIXME: Improve Escher API to accept arrays to avoid creation
+ // of many Point objects.
+ for (int i = 0; i < numPoints; i++)
+ points[i] = new Point(xPoints[i], yPoints[i]);
+ xdrawable.fill_poly(xgc, points, Drawable.COMPLEX, Drawable.ORIGIN);
+ }
+
+ /**
+ * Draws the specified string at (x, y).
+ */
+ public void drawString(String string, int x, int y)
+ {
+ if (disposed)
+ throw new AWTError("XGraphics already disposed");
+
+ xdrawable.text(xgc, x + translateX, y + translateY, string);
+ }
+
+ public void drawString(AttributedCharacterIterator ci, int x, int y)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /**
+ * Draws the specified image on the drawable at position (x,y).
+ */
+ public boolean drawImage(Image image, int x, int y, ImageObserver observer)
+ {
+ if (image instanceof XImage)
+ {
+ XImage xim = (XImage) image;
+ Pixmap pm = xim.pixmap;
+ xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height,
+ x + translateX, y + translateY);
+ }
+// else if (image instanceof BufferedImage)
+// {
+// BufferedImage bufferedImage = (BufferedImage) image;
+// Raster raster = bufferedImage.getData();
+// int w = bufferedImage.getWidth();
+// int h = bufferedImage.getHeight();
+// // Push data to X server.
+// ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h,
+// xdrawable.display.default_pixmap_format);
+// System.err.println("data buffer length: " + zPixmap.data.length);
+// int[] pixel = new int[4];
+// for (int tx = 0; tx < w; tx++)
+// {
+// for (int ty = 0; ty < h; ty++)
+// {
+// pixel = raster.getPixel(tx, ty, pixel);
+//// System.err.print("r: " + pixel[0]);
+//// System.err.print(", g: " + pixel[1]);
+//// System.err.println(", b: " + pixel[2]);
+// zPixmap.set_red(tx, ty, pixel[0]);
+// zPixmap.set_green(tx, ty, pixel[1]);
+// zPixmap.set_blue(tx, ty, pixel[2]);
+// }
+// }
+// xdrawable.put_image(xgc, zPixmap, x, y);
+// }
+ else
+ {
+ // Pre-render the image into an XImage.
+ ImageProducer source = image.getSource();
+ ImageConverter conv = new ImageConverter();
+ source.startProduction(conv);
+ XImage xim = conv.getXImage();
+ Pixmap pm = xim.pixmap;
+ xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height,
+ x + translateX, y + translateY);
+ }
+ return true;
+ }
+
+ public boolean drawImage(Image image, int x, int y, int width, int height,
+ ImageObserver observer)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public boolean drawImage(Image image, int x, int y, Color bgcolor,
+ ImageObserver observer)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public boolean drawImage(Image image, int x, int y, int width, int height,
+ Color bgcolor, ImageObserver observer)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ ImageObserver observer)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2, Color bgcolor,
+ ImageObserver observer)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /**
+ * Frees any resources associated with this object.
+ */
+ public void dispose()
+ {
+ xdrawable.display.flush();
+ if (! disposed)
+ {
+ xgc.free();
+ disposed = true;
+ }
+ }
+
+ // Additional Graphics2D methods.
+
+ public void draw(Shape shape)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public boolean drawImage(Image image, AffineTransform xform, ImageObserver obs)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void drawRenderableImage(RenderableImage image, AffineTransform xform)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void drawString(String text, float x, float y)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void drawString(AttributedCharacterIterator iterator, float x, float y)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void fill(Shape shape)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public boolean hit(Rectangle rect, Shape text, boolean onStroke)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setComposite(Composite comp)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setPaint(Paint paint)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setStroke(Stroke stroke)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setRenderingHint(Key hintKey, Object hintValue)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public Object getRenderingHint(Key hintKey)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setRenderingHints(Map hints)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void addRenderingHints(Map hints)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public RenderingHints getRenderingHints()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void translate(double tx, double ty)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void rotate(double theta)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void rotate(double theta, double x, double y)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void scale(double scaleX, double scaleY)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void shear(double shearX, double shearY)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void transform(AffineTransform Tx)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setTransform(AffineTransform Tx)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public AffineTransform getTransform()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public Paint getPaint()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public Composite getComposite()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void setBackground(Color color)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public Color getBackground()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public Stroke getStroke()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void clip(Shape s)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public FontRenderContext getFontRenderContext()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void drawGlyphVector(GlyphVector g, float x, float y)
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+
+ // Additional helper methods.
+
+ /**
+ * Creates and returns an exact copy of this XGraphics.
+ */
+ protected Object clone()
+ {
+ try
+ {
+ XGraphics copy = (XGraphics) super.clone();
+ copy.xgc = xgc.copy();
+
+ // Save the original clip.
+ if (clip != null)
+ copy.clip = new Rectangle(clip);
+ return copy;
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ AWTError err = new AWTError("Error while cloning XGraphics");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+
+ /**
+ * Computes the intersection between two rectangles and stores the result
+ * int the second rectangle.
+ *
+ * This method has been copied from {@link javax.swing.SwingUtilities}.
+ *
+ * @param x the x coordinate of the rectangle #1
+ * @param y the y coordinate of the rectangle #1
+ * @param w the width of the rectangle #1
+ * @param h the height of the rectangle #1
+ * @param rect the rectangle #2 and output rectangle
+ */
+ private static void computeIntersection(int x, int y, int w, int h,
+ Rectangle rect)
+ {
+ int x2 = (int) rect.x;
+ int y2 = (int) rect.y;
+ int w2 = (int) rect.width;
+ int h2 = (int) rect.height;
+
+ int dx = (x > x2) ? x : x2;
+ int dy = (y > y2) ? y : y2;
+ int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx);
+ int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy);
+
+ if (dw >= 0 && dh >= 0)
+ rect.setBounds(dx, dy, dw, dh);
+ else
+ rect.setBounds(0, 0, 0, 0);
+ }
+
+
+}
diff --git a/gnu/java/awt/peer/x/XGraphics2D.java b/gnu/java/awt/peer/x/XGraphics2D.java
new file mode 100644
index 000000000..5dc79ff5c
--- /dev/null
+++ b/gnu/java/awt/peer/x/XGraphics2D.java
@@ -0,0 +1,295 @@
+/* XGraphics2D.java -- A Java based Graphics2D impl for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.geom.AffineTransform;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+
+import gnu.java.awt.java2d.AbstractGraphics2D;
+import gnu.x11.Drawable;
+import gnu.x11.GC;
+import gnu.x11.image.ZPixmap;
+
+public class XGraphics2D
+ extends AbstractGraphics2D
+{
+
+ /**
+ * The X Drawable to draw on.
+ */
+ private Drawable xdrawable;
+
+ /**
+ * The X graphics context (GC).
+ */
+ private GC xgc;
+
+ /**
+ * Indicates if this graphics has already been disposed.
+ */
+ private boolean disposed;
+
+ XGraphics2D(Drawable d)
+ {
+ super();
+ xdrawable = d;
+ xgc = new GC(d);
+ init();
+ disposed = false;
+ //setClip(new Rectangle(0, 0, xdrawable.width, xdrawable.height));
+ }
+
+ /**
+ * Draws a pixel in the target coordinate space using the specified color.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ protected void rawSetPixel(int x, int y)
+ {
+ xdrawable.point(xgc, x, y);
+ }
+
+// protected void rawFillPolygon(double[] xpoints, double[] ypoints, int npoints)
+// {
+// Point[] points = new Point[npoints];
+// for (int n = 0; n < npoints; n++)
+// {
+// points[n] = new Point((int) xpoints[n], (int) ypoints[n]);
+// }
+// xdrawable.fill_poly(xgc, points, Drawable.COMPLEX, Drawable.ORIGIN);
+// xdrawable.display.flush();
+// }
+
+ protected void rawDrawLine(int x0, int y0, int x1, int y1)
+ {
+ xdrawable.line(xgc, x0, y0, x1, y1);
+ }
+
+ protected void rawFillRect(int x, int y, int w, int h)
+ {
+ xdrawable.rectangle(xgc, x, y, w, h, true);
+ }
+
+ protected void rawSetForeground(java.awt.Color c)
+ {
+ if (c != null)
+ xgc.set_foreground(c.getRGB());
+ }
+
+ protected void rawSetForeground(int r, int g, int b)
+ {
+ xgc.set_foreground( r << 16 | g << 8 | b );
+ }
+
+ /**
+ * Returns the color model of this Graphics object.
+ *
+ * @return the color model of this Graphics object
+ */
+ protected ColorModel getColorModel()
+ {
+ return Toolkit.getDefaultToolkit().getColorModel();
+ }
+
+ /**
+ * Returns the color model of the target device.
+ *
+ * @return the color model of the target device
+ */
+ protected ColorModel getDestinationColorModel()
+ {
+ return Toolkit.getDefaultToolkit().getColorModel();
+ }
+
+ /**
+ * Returns the bounds of the target.
+ *
+ * @return the bounds of the target
+ */
+ protected Rectangle getDeviceBounds()
+ {
+ return new Rectangle(0, 0, xdrawable.width, xdrawable.height);
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void dispose()
+ {
+ if (!disposed)
+ {
+ xgc.free();
+ xdrawable.display.flush();
+ disposed = true;
+ }
+ }
+
+ public Graphics create()
+ {
+ // super.create() returns a copy created by clone(), so it should
+ // be a XGraphics2D.
+ XGraphics2D copy = (XGraphics2D) super.create();
+ copy.xgc = xgc.copy();
+ return copy;
+ }
+
+// /**
+// * Draws the specified image on the drawable at position (x,y).
+// */
+//
+// public boolean drawImage(Image image, int x, int y, ImageObserver observer)
+// {
+// AffineTransform transform = getTransform();
+// int translateX = (int) transform.getTranslateX();
+// int translateY = (int) transform.getTranslateY();
+// if (image instanceof XImage)
+// {
+// XImage xim = (XImage) image;
+// Pixmap pm = xim.pixmap;
+// xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height,
+// x + translateX, y + translateY);
+// }
+// else if (image instanceof BufferedImage)
+// {
+// BufferedImage bufferedImage = (BufferedImage) image;
+// Raster raster = bufferedImage.getData();
+// int w = bufferedImage.getWidth();
+// int h = bufferedImage.getHeight();
+// // Push data to X server.
+// ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h,
+// xdrawable.display.default_pixmap_format);
+// System.err.println("data buffer length: " + zPixmap.data.length);
+// int[] pixel = new int[4];
+// for (int tx = 0; tx < w; tx++)
+// {
+// for (int ty = 0; ty < h; ty++)
+// {
+// pixel = raster.getPixel(tx, ty, pixel);
+//// System.err.print("r: " + pixel[0]);
+//// System.err.print(", g: " + pixel[1]);
+//// System.err.println(", b: " + pixel[2]);
+// zPixmap.set_red(tx, ty, pixel[0]);
+// zPixmap.set_green(tx, ty, pixel[1]);
+// zPixmap.set_blue(tx, ty, pixel[2]);
+// }
+// }
+// xdrawable.put_image(xgc, zPixmap, x, y);
+// }
+// else
+// {
+// throw new UnsupportedOperationException("Not yet implemented.");
+// }
+// return true;
+// }
+//
+ public void setClip(Shape c)
+ {
+ super.setClip(c);
+ if (c instanceof Rectangle)
+ {
+ Rectangle r = (Rectangle) c;
+ AffineTransform t = getTransform();
+ int translateX = (int) t.getTranslateX();
+ //System.err.println("translateX: " + translateX);
+ int translateY = (int) t.getTranslateY();
+ //System.err.println("translateY: " + translateY);
+ //System.err.println("clip: " + c);
+ gnu.x11.Rectangle clip = new gnu.x11.Rectangle(r.x, r.y, r.width,
+ r.height);
+ xgc.set_clip_rectangles(translateX, translateY,
+ new gnu.x11.Rectangle[]{clip}, GC.UN_SORTED);
+ }
+ }
+
+ /**
+ * 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)
+ {
+ if (w > 0 && h > 0)
+ {
+ ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h,
+ xdrawable.display.default_pixmap_format);
+ int[] pixel = null;
+ int x1 = x + w;
+ int y1 = y + h;
+ for (int tx = x; tx < x1; tx++)
+ {
+ for (int ty = y; ty < y1; ty++)
+ {
+ pixel = raster.getPixel(tx, ty, pixel);
+ //System.err.println("tx: " + tx + ", ty: " + ty + ", pixel: " + pixel[0] + ", " + pixel[1] + ", " + pixel[2]);
+// System.err.print("r: " + pixel[0]);
+// System.err.print(", g: " + pixel[1]);
+// System.err.println(", b: " + pixel[2]);
+ zPixmap.set_red(tx - x, ty - y, pixel[0]);
+ zPixmap.set_green(tx - x, ty - y, pixel[1]);
+ zPixmap.set_blue(tx - x, ty - y, pixel[2]);
+ }
+ }
+ xdrawable.put_image(xgc, zPixmap, x, y);
+ }
+ }
+
+
+ protected void init()
+ {
+ super.init();
+ }
+}
diff --git a/gnu/java/awt/peer/x/XGraphicsConfiguration.java b/gnu/java/awt/peer/x/XGraphicsConfiguration.java
new file mode 100644
index 000000000..d6e66cbd2
--- /dev/null
+++ b/gnu/java/awt/peer/x/XGraphicsConfiguration.java
@@ -0,0 +1,118 @@
+/* XGraphicsConfiguration.java -- GraphicsConfiguration for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.VolatileImage;
+
+public class XGraphicsConfiguration
+ extends GraphicsConfiguration
+{
+
+ XGraphicsDevice device;
+
+ XGraphicsConfiguration(XGraphicsDevice dev)
+ {
+ device = dev;
+ }
+
+ public GraphicsDevice getDevice()
+ {
+ return device;
+ }
+
+ public BufferedImage createCompatibleImage(int w, int h)
+ {
+ return new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int w, int h)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int width, int height,
+ int transparency)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public BufferedImage createCompatibleImage(int w, int h, int transparency)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public ColorModel getColorModel()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public ColorModel getColorModel(int transparency)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public AffineTransform getDefaultTransform()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public AffineTransform getNormalizingTransform()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Rectangle getBounds()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+}
diff --git a/gnu/java/awt/peer/x/XGraphicsDevice.java b/gnu/java/awt/peer/x/XGraphicsDevice.java
new file mode 100644
index 000000000..6a020ec4e
--- /dev/null
+++ b/gnu/java/awt/peer/x/XGraphicsDevice.java
@@ -0,0 +1,166 @@
+/* XGraphicsDevice.java -- GraphicsDevice for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import gnu.classpath.SystemProperties;
+import gnu.java.net.local.LocalSocket;
+import gnu.java.net.local.LocalSocketAddress;
+import gnu.x11.Connection;
+import gnu.x11.Display;
+
+import java.awt.AWTError;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.net.SocketException;
+
+/**
+ * This class represents an X Display. The actual connection is established
+ * lazily when it is first needed.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XGraphicsDevice
+ extends GraphicsDevice
+{
+
+ private XGraphicsConfiguration defaultConfiguration;
+
+ /**
+ * The X display associated with the XGraphicsDevice. This is established
+ * when {@link #getDisplay} is first called.
+ */
+ private Display display;
+
+ /**
+ * The display name from which the display will be initialized.
+ */
+ private Display.Name displayName;
+
+ /**
+ * The event pump for this X Display.
+ */
+ private XEventPump eventPump;
+
+ /**
+ * Creates a new XGraphicsDevice.
+ */
+ XGraphicsDevice(Display.Name dn)
+ {
+ displayName = dn;
+ }
+
+ public int getType()
+ {
+ return TYPE_RASTER_SCREEN;
+ }
+
+ public String getIDstring()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GraphicsConfiguration[] getConfigurations()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GraphicsConfiguration getDefaultConfiguration()
+ {
+ if (defaultConfiguration == null)
+ defaultConfiguration = new XGraphicsConfiguration(this);
+ return defaultConfiguration;
+ }
+
+ /**
+ * Returns the X Display associated with this XGraphicsDevice.
+ * This establishes the connection to the X server on the first invocation.
+ *
+ * @return the X Display associated with this XGraphicsDevice
+ */
+ Display getDisplay()
+ {
+ if (display == null)
+ {
+ if (displayName.hostname.equals(""))
+ displayName.hostname = "localhost";
+ if (XToolkit.DEBUG)
+ System.err.println("connecting to : " + displayName);
+ // Try to connect via unix domain sockets when host == localhost.
+ if ((displayName.hostname.equals("localhost")
+ || displayName.hostname.equals(""))
+ && SystemProperties.getProperty("gnu.xawt.no_local_sockets") == null)
+ {
+ // TODO: Is this 100% ok?
+ String sockPath = "/tmp/.X11-unix/X" + displayName.display_no;
+ LocalSocketAddress addr = new LocalSocketAddress(sockPath);
+ try
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("connecting to local socket: "
+ + sockPath);
+ LocalSocket socket = new LocalSocket(addr);
+ display = new Display(socket, "localhost",
+ displayName.display_no,
+ displayName.screen_no);
+ display.connection.send_mode = Connection.ASYNCHRONOUS;
+ if (XToolkit.DEBUG)
+ System.err.println("connected to local socket");
+ }
+ catch (SocketException ex)
+ {
+ AWTError err = new AWTError("could not connect to X server");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+ else
+ {
+ display = new Display(displayName);
+ }
+ eventPump = new XEventPump(display);
+ }
+ return display;
+ }
+
+ XEventPump getEventPump()
+ {
+ return eventPump;
+ }
+}
diff --git a/gnu/java/awt/peer/x/XGraphicsEnvironment.java b/gnu/java/awt/peer/x/XGraphicsEnvironment.java
new file mode 100644
index 000000000..707b44c38
--- /dev/null
+++ b/gnu/java/awt/peer/x/XGraphicsEnvironment.java
@@ -0,0 +1,202 @@
+/* XGraphicsEnvironment.java -- Represents the X environment
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import gnu.java.awt.java2d.RasterGraphics;
+import gnu.x11.Display;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.Properties;
+
+/**
+ * Represents the X environment for AWT.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XGraphicsEnvironment
+ extends GraphicsEnvironment
+{
+
+ /**
+ * The default graphics device. This is normally the local main X
+ * Display, but can be configured to be any X connection.
+ */
+ private XGraphicsDevice defaultDevice;
+
+ /**
+ * All configured devices.
+ */
+ private XGraphicsDevice[] devices;
+
+ /**
+ * Creates a new XGraphicsEnvironment. This loads the configuration if
+ * there is one present and initializes the XGraphicsDevices in the
+ * environment. If there is no configuration, then there is one
+ * default device initialized with the local main X device.
+ */
+ XGraphicsEnvironment()
+ {
+ // Initiliaze the devices.
+ Properties props = new Properties();
+ File config = new File(System.getProperty("user.home"),
+ ".xawt.properties");
+
+ try
+ {
+ FileInputStream configIn = new FileInputStream(config);
+ props.load(configIn);
+ int dev = 1;
+ ArrayList deviceList = new ArrayList();
+ while (true)
+ {
+ String propName = "display." + dev;
+ String propValue = props.getProperty(propName);
+ if (propValue != null)
+ {
+ Display.Name displayName = new Display.Name(propValue);
+ XGraphicsDevice device = new XGraphicsDevice(displayName);
+ if (dev == 1)
+ defaultDevice = device;
+ deviceList.add(device);
+ dev++;
+ }
+ else
+ {
+ if (dev == 1)
+ {
+ defaultDevice = initDefaultDevice();
+ deviceList.add(defaultDevice);
+ }
+ break;
+ }
+ }
+ devices = (XGraphicsDevice[]) deviceList.toArray
+ (new XGraphicsDevice[deviceList.size()]);
+ }
+ catch (FileNotFoundException ex)
+ {
+ defaultDevice = initDefaultDevice();
+ devices = new XGraphicsDevice[]{ defaultDevice };
+ }
+ catch (IOException ex)
+ {
+ defaultDevice = initDefaultDevice();
+ devices = new XGraphicsDevice[]{ defaultDevice };
+ }
+
+ }
+
+ /**
+ * Helper method that initializes the default device in the case when there
+ * is no configuration for the default.
+ */
+ private XGraphicsDevice initDefaultDevice()
+ {
+ String display = System.getenv("DISPLAY");
+ if (display == null)
+ display = ":0.0";
+ Display.Name displayName = new Display.Name(display);
+ return new XGraphicsDevice(displayName);
+ }
+
+ /**
+ * Returns all configured screen devices.
+ *
+ * @return all configured screen devices
+ */
+ public GraphicsDevice[] getScreenDevices()
+ {
+ // We return a copy so that nobody can fiddle with our devices.
+ XGraphicsDevice[] copy = new XGraphicsDevice[devices.length];
+ System.arraycopy(devices, 0, copy, 0, devices.length);
+ return copy;
+ }
+
+ /**
+ * Returns the default screen device.
+ *
+ * @return the default screen device
+ */
+ public GraphicsDevice getDefaultScreenDevice()
+ {
+ return defaultDevice;
+ }
+
+ /**
+ * Returns a Graphics instance suitable for drawing on top of the
+ * BufferedImage.
+ *
+ * @param image the buffered image to create a graphics for
+ *
+ * @return a Graphics2D instance for drawing on the BufferedImage
+ */
+ public Graphics2D createGraphics(BufferedImage image)
+ {
+ return new RasterGraphics(image.getRaster(), image.getColorModel());
+ }
+
+ public Font[] getAllFonts()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String[] getAvailableFontFamilyNames()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String[] getAvailableFontFamilyNames(Locale l)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+}
diff --git a/gnu/java/awt/peer/x/XImage.java b/gnu/java/awt/peer/x/XImage.java
new file mode 100644
index 000000000..28bc6b90a
--- /dev/null
+++ b/gnu/java/awt/peer/x/XImage.java
@@ -0,0 +1,107 @@
+/* XImage.java -- Image impl for X Pixmaps
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import gnu.x11.Pixmap;
+
+import java.awt.Graphics;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+
+public class XImage
+ extends Image
+{
+
+ Pixmap pixmap;
+
+ XImage(int w, int h)
+ {
+ XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit();
+ GraphicsEnvironment env = tk.getLocalGraphicsEnvironment();
+ XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice();
+ pixmap = new Pixmap(dev.getDisplay(), w, h);
+ }
+
+ public int getWidth(ImageObserver observer)
+ {
+ return pixmap.width;
+ }
+
+ public int getHeight(ImageObserver observer)
+ {
+ return pixmap.height;
+ }
+
+ public ImageProducer getSource()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Creates an XGraphics for drawing on this XImage.
+ *
+ * @return an XGraphics for drawing on this XImage
+ */
+ public Graphics getGraphics()
+ {
+ XGraphics g = new XGraphics(pixmap);
+ return g;
+ }
+
+ public Object getProperty(String name, ImageObserver observer)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void flush()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected void finalize()
+ {
+ pixmap.free();
+ }
+}
diff --git a/gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java b/gnu/java/awt/peer/x/XLightweightPeer.java
index 46b0733d3..2613d84d8 100644
--- a/gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java
+++ b/gnu/java/awt/peer/x/XLightweightPeer.java
@@ -1,5 +1,5 @@
-/* GtkCheckboxGroupPeer.java - Wrap a CheckboxGroup
- Copyright (C) 2002 Free Software Foundation, Inc.
+/* XLightweightPeer.java -- A lightweight peer for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -36,51 +36,21 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.java.awt.peer.gtk;
+package gnu.java.awt.peer.x;
-import java.awt.CheckboxGroup;
-import java.util.WeakHashMap;
+import java.awt.Component;
+import java.awt.peer.LightweightPeer;
-// Note that there is no peer interface for a CheckboxGroup. We
-// introduce our own in order to make it easier to keep a piece of
-// native state for each one.
-public class GtkCheckboxGroupPeer extends GtkGenericPeer
-{
- // This maps from a CheckboxGroup to the native peer.
- private static WeakHashMap map = new WeakHashMap ();
+import gnu.java.awt.peer.swing.SwingContainerPeer;
- // Find the native peer corresponding to a CheckboxGroup.
- public static synchronized GtkCheckboxGroupPeer
- getCheckboxGroupPeer (CheckboxGroup group)
- {
- if (group == null)
- return null;
- GtkCheckboxGroupPeer nat = (GtkCheckboxGroupPeer) map.get (group);
- if (nat == null)
- {
- nat = new GtkCheckboxGroupPeer ();
- map.put (group, nat);
- }
- return nat;
- }
-
- private GtkCheckboxGroupPeer ()
- {
- // We don't need any special state here. Note that we can't store
- // a reference to the java-side CheckboxGroup. That would mean
- // they could never be collected.
- super (null);
- }
-
- // Dispose of our native resources.
- public native void dispose ();
-
- // Remove a given checkbox from this group.
- public native void remove (GtkCheckboxPeer box);
+public class XLightweightPeer
+ extends SwingContainerPeer
+ implements LightweightPeer
+{
- // When collected, clean up the native state.
- protected void finalize ()
+ XLightweightPeer(Component c)
{
- dispose ();
+ super(c);
+ init(c, null);
}
}
diff --git a/gnu/java/awt/peer/x/XToolkit.java b/gnu/java/awt/peer/x/XToolkit.java
new file mode 100644
index 000000000..05e8a5963
--- /dev/null
+++ b/gnu/java/awt/peer/x/XToolkit.java
@@ -0,0 +1,575 @@
+/* XToolkit.java -- The central AWT Toolkit for the X peers
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.PrintJob;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Window;
+import java.awt.datatransfer.Clipboard;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.font.FontRenderContext;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.LightweightPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.AttributedString;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.WeakHashMap;
+
+import javax.imageio.ImageIO;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+import gnu.java.awt.peer.swing.SwingCanvasPeer;
+import gnu.java.awt.peer.swing.SwingLabelPeer;
+import gnu.java.awt.peer.swing.SwingPanelPeer;
+
+public class XToolkit
+ extends ClasspathToolkit
+{
+
+ /**
+ * Set to true to enable debug output.
+ */
+ static boolean DEBUG = false;
+
+ private XGraphicsEnvironment env;
+
+ /**
+ * The system event queue.
+ */
+ private EventQueue eventQueue;
+
+ /**
+ * The default color model of this toolkit.
+ */
+ private ColorModel colorModel;
+
+ /**
+ * Maps image URLs to Image instances.
+ */
+ private HashMap imageCache = new HashMap();
+
+ /**
+ * The cached fonts.
+ */
+ private WeakHashMap fontCache = new WeakHashMap();
+
+ public XToolkit()
+ {
+ System.setProperty("gnu.javax.swing.noGraphics2D", "true");
+ }
+
+ public GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ if (env == null)
+ env = new XGraphicsEnvironment();
+ return env;
+ }
+
+ /**
+ * Returns the font peer for a font with the specified name and attributes.
+ *
+ * @param name the font name
+ * @param attrs the font attributes
+ *
+ * @return the font peer for a font with the specified name and attributes
+ */
+ public ClasspathFontPeer getClasspathFontPeer(String name, Map attrs)
+ {
+ String canonical = XFontPeer.encodeFont(name, attrs);
+ XFontPeer font;
+ if (!fontCache.containsKey(canonical))
+ {
+ font = new XFontPeer(name, attrs);
+ fontCache.put(canonical, font);
+ }
+ else
+ {
+ font = (XFontPeer) fontCache.get(canonical);
+ }
+ return font;
+ }
+
+ public Font createFont(int format, InputStream stream)
+ {
+ return null;
+ }
+
+ public RobotPeer createRobot(GraphicsDevice screen) throws AWTException
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public EmbeddedWindowPeer createEmbeddedWindow(EmbeddedWindow w)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected ButtonPeer createButton(Button target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected TextFieldPeer createTextField(TextField target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected LabelPeer createLabel(Label target)
+ {
+ return new SwingLabelPeer(target);
+ }
+
+ protected ListPeer createList(List target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected CheckboxPeer createCheckbox(Checkbox target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected ScrollbarPeer createScrollbar(Scrollbar target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected ScrollPanePeer createScrollPane(ScrollPane target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected TextAreaPeer createTextArea(TextArea target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected ChoicePeer createChoice(Choice target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected FramePeer createFrame(Frame target)
+ {
+ XFramePeer frame = new XFramePeer(target);
+ return frame;
+ }
+
+ protected CanvasPeer createCanvas(Canvas target)
+ {
+ return new SwingCanvasPeer(target);
+ }
+
+ protected PanelPeer createPanel(Panel target)
+ {
+ return new SwingPanelPeer(target);
+ }
+
+ protected WindowPeer createWindow(Window target)
+ {
+ return new XWindowPeer(target);
+ }
+
+ protected DialogPeer createDialog(Dialog target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected MenuBarPeer createMenuBar(MenuBar target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected MenuPeer createMenu(Menu target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected PopupMenuPeer createPopupMenu(PopupMenu target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected MenuItemPeer createMenuItem(MenuItem target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected FileDialogPeer createFileDialog(FileDialog target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected FontPeer getFontPeer(String name, int style)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Dimension getScreenSize()
+ {
+ // FIXME: This is only a hack to get some apps working.
+ return new Dimension(1024, 768);
+ }
+
+ public int getScreenResolution()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns the color model used by this toolkit.
+ *
+ * @return the color model used by this toolkit
+ */
+ public ColorModel getColorModel()
+ {
+ // TODO: I assume 24 bit depth here, we can do this better.
+ if (colorModel == null)
+ colorModel = new DirectColorModel(24, 0xFF0000, 0xFF00, 0xFF);
+ return colorModel;
+ }
+
+ public String[] getFontList()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public FontMetrics getFontMetrics(Font name)
+ {
+ XFontPeer peer = (XFontPeer) name.getPeer();
+ return peer.getFontMetrics(name);
+ }
+
+ public void sync()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from a file with the
+ * specified name. If that file doesn't exist, an empty or error image
+ * is returned instead.
+ *
+ * @param name the filename of the file that contains the pixel data
+ *
+ * @return the image
+ */
+ public Image getImage(String name)
+ {
+ Image image;
+ try
+ {
+ File file = new File(name);
+ image = getImage(file.toURL());
+ }
+ catch (MalformedURLException ex)
+ {
+ // TODO: Replace by a more meaningful error image instead.
+ image = null;
+ }
+ return image;
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from the specified URL.
+ * If the image cannot be loaded for some reason, an empty or error image
+ * is returned instead.
+ *
+ * @param url the URL to the image data
+ *
+ * @return the image
+ */
+ public Image getImage(URL url)
+ {
+ Image image;
+ if (imageCache.containsKey(url))
+ {
+ image = (Image) imageCache.get(url);
+ }
+ else
+ {
+ image = createImage(url);
+ imageCache.put(url, image);
+ }
+ return image;
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from a file with the
+ * specified name. If that file doesn't exist, an empty or error image
+ * is returned instead.
+ *
+ * @param filename the filename of the file that contains the pixel data
+ *
+ * @return the image
+ */
+ public Image createImage(String filename)
+ {
+ Image im;
+ try
+ {
+ File file = new File(filename);
+ URL url = file.toURL();
+ im = createImage(url);
+ }
+ catch (MalformedURLException ex)
+ {
+ im = createErrorImage();
+ }
+ return im;
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from the specified URL.
+ * If the image cannot be loaded for some reason, an empty or error image
+ * is returned instead.
+ *
+ * @param url the URL to the image data
+ *
+ * @return the image
+ */
+ public Image createImage(URL url)
+ {
+ Image image;
+ try
+ {
+ BufferedImage buffered = ImageIO.read(url);
+ if (buffered != null)
+ {
+ ImageConverter conv = new ImageConverter();
+ ImageProducer source = buffered.getSource();
+ source.startProduction(conv);
+ return conv.getXImage();
+ }
+ else return createErrorImage();
+
+ }
+ catch (IOException ex)
+ {
+ image = createErrorImage();
+ }
+ return image;
+ }
+
+ /**
+ * Creates an image that is returned when calls to createImage() yields an
+ * error.
+ *
+ * @return an image that is returned when calls to createImage() yields an
+ * error
+ */
+ private Image createErrorImage()
+ {
+ // TODO: Create better error image.
+ return new XImage(1, 1);
+ }
+
+ public boolean prepareImage(Image image, int width, int height, ImageObserver observer)
+ {
+ // Images are loaded synchronously, so we don't bother and return true.
+ return true;
+ }
+
+ public int checkImage(Image image, int width, int height, ImageObserver observer)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Image createImage(ImageProducer producer)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Image createImage(byte[] data, int offset, int len)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public PrintJob getPrintJob(Frame frame, String title, Properties props)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void beep()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Clipboard getSystemClipboard()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns the eventqueue used by the XLib peers.
+ *
+ * @return the eventqueue used by the XLib peers
+ */
+ protected EventQueue getSystemEventQueueImpl()
+ {
+ if (eventQueue == null)
+ eventQueue = new EventQueue();
+ return eventQueue;
+ }
+
+ public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Map mapInputMethodHighlight(InputMethodHighlight highlight)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Helper method to quickly fetch the default device (X Display).
+ *
+ * @return the default XGraphicsDevice
+ */
+ static XGraphicsDevice getDefaultDevice()
+ {
+ XGraphicsEnvironment env = (XGraphicsEnvironment)
+ XGraphicsEnvironment.getLocalGraphicsEnvironment();
+ return (XGraphicsDevice) env.getDefaultScreenDevice();
+ }
+
+ protected LightweightPeer createComponent(Component c)
+ {
+ return new XLightweightPeer(c);
+ }
+}
diff --git a/gnu/java/awt/peer/x/XWindowPeer.java b/gnu/java/awt/peer/x/XWindowPeer.java
new file mode 100644
index 000000000..f4815ce7f
--- /dev/null
+++ b/gnu/java/awt/peer/x/XWindowPeer.java
@@ -0,0 +1,256 @@
+/* XWindowPeer.java -- Window peer for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+
+import gnu.x11.Window;
+import gnu.x11.event.Event;
+
+import gnu.java.awt.peer.swing.SwingWindowPeer;
+
+public class XWindowPeer
+ extends SwingWindowPeer
+{
+
+ private static int standardSelect = Event.BUTTON_PRESS_MASK
+ | Event.BUTTON_RELEASE_MASK
+ | Event.POINTER_MOTION_MASK
+ //| Event.RESIZE_REDIRECT_MASK
+ | Event.EXPOSURE_MASK
+ //| Event.PROPERTY_CHANGE_MASK
+ | Event.STRUCTURE_NOTIFY_MASK
+ | Event.KEY_PRESS_MASK
+ | Event.KEY_RELEASE_MASK
+ ;
+
+ /**
+ * Indicates if we are in callback mode, that is when a property (like size)
+ * is changed in reponse to a request from the X server and doesn't need
+ * to be propagated back to the X server.
+ */
+ boolean callback = false;
+
+ /**
+ * The X window.
+ */
+ private Window xwindow;
+
+ XWindowPeer(java.awt.Window window)
+ {
+ super(window);
+ System.err.println("new XWindowPeer");
+ XGraphicsDevice dev = XToolkit.getDefaultDevice();
+
+ // TODO: Maybe initialize lazily in show().
+ // FIXME: Howto generate a Window without decorations?
+ int x = Math.max(window.getX(), 0);
+ int y = Math.max(window.getY(), 0);
+ int w = Math.max(window.getWidth(), 1);
+ int h = Math.max(window.getHeight(), 1);
+ xwindow = new Window(dev.getDisplay().default_root, x, y, w, h);
+ xwindow.create();
+ xwindow.select_input(standardSelect);
+ dev.getEventPump().registerWindow(xwindow, window);
+ }
+
+ public void toBack()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void toFront()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateAlwaysOnTop()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean requestWindowFocus()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public Point getLocationOnScreen()
+ {
+ return new Point(xwindow.x, xwindow.y);
+ }
+
+ /**
+ * Returns a XGraphics suitable for drawing on this frame.
+ *
+ * @return a XGraphics suitable for drawing on this frame
+ */
+ public Graphics getGraphics()
+ {
+ return new XGraphics(xwindow);
+ }
+
+ public Image createImage(int w, int h)
+ {
+ return new XImage(w, h);
+ }
+
+ /**
+ * Makes the component visible. This is called by {@link Component#show()}.
+ *
+ * This is implemented to call setVisible(true) on the Swing component.
+ */
+ public void show()
+ {
+// // Prevent ResizeRedirect events.
+// //xwindow.select_input(noResizeRedirectSelect);
+// Window.Attributes atts = new Window.Attributes();
+// atts.set_override_redirect(true);
+// xwindow.change_attributes(atts);
+
+ // Prevent ResizeRedirect events.
+ //xwindow.select_input(Event.NO_EVENT_MASK);
+ //xwindow.select_input(noResizeRedirectSelect);
+
+ xwindow.map();
+ EventQueue eq = XToolkit.getDefaultToolkit().getSystemEventQueue();
+ java.awt.Window w = (java.awt.Window) super.awtComponent;
+ eq.postEvent(new WindowEvent(w, WindowEvent.WINDOW_OPENED));
+ eq.postEvent(new PaintEvent(w, PaintEvent.PAINT,
+ new Rectangle(0, 0, w.getWidth(),
+ w.getHeight())));
+
+// // Reset input selection.
+// atts.set_override_redirect(false);
+// xwindow.change_attributes(atts);
+ }
+
+ /**
+ * Makes the component invisible. This is called from
+ * {@link Component#hide()}.
+ *
+ * This is implemented to call setVisible(false) on the Swing component.
+ */
+ public void hide()
+ {
+ xwindow.unmap();
+ }
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#reshape(int, int, int, int)}.
+ *
+ * This is implemented to call setBounds() on the Swing component.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ // Prevent ResizeRedirect events.
+// //xwindow.select_input(noResizeRedirectSelect);
+// Window.Attributes atts = new Window.Attributes();
+// atts.set_override_redirect(true);
+// xwindow.change_attributes(atts);
+
+ // Need to substract insets because AWT size is including insets,
+ // and X size is excuding insets.
+ Insets i = insets();
+ xwindow.move_resize(x - i.left, y - i.right, width - i.left - i.right,
+ height - i.top - i.bottom);
+
+ // Reset input selection.
+// atts = new Window.Attributes();
+// atts.set_override_redirect(false);
+// xwindow.change_attributes(atts);
+ }
+
+ public Insets insets()
+ {
+ Insets i = new Insets(0, 0, 0, 0);
+// Window.GeometryReply g = xwindow.geometry();
+// int b = g.border_width();
+// Insets i = new Insets(b, b, b, b);
+// Window.WMSizeHints wmSize = xwindow.wm_normal_hints();
+// if (wmSize != null)
+// {
+// i.left = wmSize.x() - g.x();
+// i.right = wmSize.width() - g.width() - i.left ;
+// i.top = wmSize.y() - g.y();
+// i.bottom = wmSize.height() - g.height() - i.top;
+// }
+// System.err.println("insets: " + i);
+ return i;
+ }
+
+ /**
+ * Returns the font metrics for the specified font.
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ XFontPeer fontPeer = (XFontPeer) font.getPeer();
+ return fontPeer.getFontMetrics(font);
+ }
+
+ /**
+ * Unregisters the window in the event pump when it is closed.
+ */
+ protected void finalize()
+ {
+ XGraphicsDevice dev = XToolkit.getDefaultDevice();
+ dev.getEventPump().unregisterWindow(xwindow);
+ }
+}
diff --git a/gnu/java/awt/peer/x/fonts.properties b/gnu/java/awt/peer/x/fonts.properties
new file mode 100644
index 000000000..2c8755ceb
--- /dev/null
+++ b/gnu/java/awt/peer/x/fonts.properties
@@ -0,0 +1,25 @@
+
+serif.plain=-adobe-times-medium-r-normal--%d-*-*-*-p-*-iso8859-1
+serif.bold=-adobe-times-bold-r-normal--%d-*-*-*-p-*-iso8859-1
+serif.italic=-adobe-times-medium-o-normal--%d-*-*-*-p-*-iso8859-1
+serif.bolditalic=-adobe-times-bold-o-normal--%d-*-*-*-p-*-iso8859-1
+
+sansserif.plain=-adobe-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1
+sansserif.bold=-adobe-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1
+sansserif.italic=-adobe-helvetica-medium-o-normal--%d-*-*-*-p-*-iso8859-1
+sansserif.bolditalic=-adobe-helvetica-bold-o-normal--%d-*-*-*-p-*-iso8859-1
+
+monospaced.plain=-adobe-courier-medium-r-normal--%d-*-*-*-p-*-iso8859-1
+monospaced.bold=-adobe-courier-bold-r-normal--%d-*-*-*-p-*-iso8859-1
+monospaced.italic=-adobe-courier-medium-o-normal--%d-*-*-*-p-*-iso8859-1
+monospaced.bolditalic=-adobe-courier-bold-o-normal--%d-*-*-*-p-*-iso8859-1
+
+dialog.plain=-adobe-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1
+dialog.bold=-adobe-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1
+dialog.italic=-adobe-helvetica-medium-o-normal--%d-*-*-*-p-*-iso8859-1
+dialog.bolditalic=-adobe-helvetica-bold-o-normal--%d-*-*-*-p-*-iso8859-1
+
+dialoginput.plain=-adobe-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1
+dialoginput.bold=-adobe-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1
+dialoginput.italic=-adobe-helvetica-medium-o-normal--%d-*-*-*-p-*-iso8859-1
+dialoginput.bolditalic=-adobe-helvetica-bold-o-normal--%d-*-*-*-p-*-iso8859-1