summaryrefslogtreecommitdiff
path: root/gnu/java
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/java')
-rw-r--r--gnu/java/awt/ClasspathToolkit.java6
-rw-r--r--gnu/java/awt/peer/ClasspathFontPeer.java4
-rw-r--r--gnu/java/awt/peer/ClasspathTextLayoutPeer.java111
-rw-r--r--gnu/java/awt/peer/gtk/GdkClasspathFontPeerMetrics.java119
-rw-r--r--gnu/java/awt/peer/gtk/GdkFontMetrics.java79
-rw-r--r--gnu/java/awt/peer/gtk/GdkFontPeer.java (renamed from gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java)93
-rw-r--r--gnu/java/awt/peer/gtk/GdkGlyphVector.java6
-rw-r--r--gnu/java/awt/peer/gtk/GdkGraphics.java10
-rw-r--r--gnu/java/awt/peer/gtk/GdkGraphics2D.java392
-rw-r--r--gnu/java/awt/peer/gtk/GdkTextLayout.java435
-rw-r--r--gnu/java/awt/peer/gtk/GtkComponentPeer.java2
-rw-r--r--gnu/java/awt/peer/gtk/GtkTextAreaPeer.java18
-rw-r--r--gnu/java/awt/peer/gtk/GtkTextFieldPeer.java18
-rw-r--r--gnu/java/awt/peer/gtk/GtkToolkit.java97
14 files changed, 860 insertions, 530 deletions
diff --git a/gnu/java/awt/ClasspathToolkit.java b/gnu/java/awt/ClasspathToolkit.java
index 92934593d..545e65356 100644
--- a/gnu/java/awt/ClasspathToolkit.java
+++ b/gnu/java/awt/ClasspathToolkit.java
@@ -47,6 +47,7 @@ import java.awt.FontMetrics;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Toolkit;
+import java.awt.font.FontRenderContext;
import java.awt.image.ColorModel;
import java.awt.image.ImageProducer;
import java.io.File;
@@ -54,10 +55,12 @@ import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
+import java.text.AttributedString;
import java.util.HashMap;
import java.util.Map;
import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.ClasspathTextLayoutPeer;
/**
@@ -171,6 +174,9 @@ public abstract class ClasspathToolkit
public abstract ClasspathFontPeer getClasspathFontPeer (String name, Map attrs);
+ public abstract ClasspathTextLayoutPeer
+ getClasspathTextLayoutPeer (AttributedString str, FontRenderContext frc);
+
/**
* Creates a {@link Font}, in a platform-specific manner.
diff --git a/gnu/java/awt/peer/ClasspathFontPeer.java b/gnu/java/awt/peer/ClasspathFontPeer.java
index 6b753aa15..6bd3653ed 100644
--- a/gnu/java/awt/peer/ClasspathFontPeer.java
+++ b/gnu/java/awt/peer/ClasspathFontPeer.java
@@ -160,7 +160,7 @@ public abstract class ClasspathFontPeer
return name;
}
- protected static void copyStyleToAttrs (int style, Map attrs)
+ public static void copyStyleToAttrs (int style, Map attrs)
{
if ((style & Font.BOLD) == Font.BOLD)
attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
@@ -179,7 +179,7 @@ public abstract class ClasspathFontPeer
attrs.put (TextAttribute.FAMILY, fam);
}
- protected static void copySizeToAttrs (float size, Map attrs)
+ public static void copySizeToAttrs (float size, Map attrs)
{
attrs.put (TextAttribute.SIZE, new Float (size));
}
diff --git a/gnu/java/awt/peer/ClasspathTextLayoutPeer.java b/gnu/java/awt/peer/ClasspathTextLayoutPeer.java
new file mode 100644
index 000000000..143412caf
--- /dev/null
+++ b/gnu/java/awt/peer/ClasspathTextLayoutPeer.java
@@ -0,0 +1,111 @@
+/* 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., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 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.Font;
+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;
+import java.text.CharacterIterator;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.Map;
+import java.awt.font.TextAttribute;
+
+
+/**
+ * @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/GdkClasspathFontPeerMetrics.java b/gnu/java/awt/peer/gtk/GdkClasspathFontPeerMetrics.java
deleted file mode 100644
index 7f9cfcd91..000000000
--- a/gnu/java/awt/peer/gtk/GdkClasspathFontPeerMetrics.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/* GdkClasspathFontPeerMetrics.java
- Copyright (C) 1999, 2002, 2004 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., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 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.FontMetrics;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-
-public class GdkClasspathFontPeerMetrics extends FontMetrics
-{
- private final int native_state = GtkGenericPeer.getUniqueInteger();
-
- private static final int ASCENT = 0, MAX_ASCENT = 1,
- DESCENT = 2, MAX_DESCENT = 3,
- MAX_ADVANCE = 4;
-
- private int[] metrics;
- private native int[] initState (Object font);
-
- public GdkClasspathFontPeerMetrics (Font font)
- {
- super (font);
- metrics = initState (font.getPeer());
- }
-
- public int stringWidth (String str)
- {
- GlyphVector gv = font.createGlyphVector
- (new FontRenderContext
- (new AffineTransform (), false, false), str);
- Rectangle2D r = gv.getVisualBounds ();
- return (int) r.getWidth ();
- }
-
- public int charWidth (char ch)
- {
- return stringWidth (new String (new char[] { ch }));
- }
-
- public int charsWidth (char data[], int off, int len)
- {
- return stringWidth (new String (data, off, len));
- }
-
- /*
- Sun's Motif implementation always returns 0 or 1 here (???), but
- going by the X11 man pages, it seems as though we should return
- font.ascent + font.descent.
- */
- public int getLeading ()
- {
- return 1;
-// return metrics[ASCENT] + metrics[DESCENT];
- }
-
- public int getAscent ()
- {
- return metrics[ASCENT];
- }
-
- public int getMaxAscent ()
- {
- return metrics[MAX_ASCENT];
- }
-
- public int getDescent ()
- {
- return metrics[DESCENT];
- }
-
- public int getMaxDescent ()
- {
- return metrics[MAX_DESCENT];
- }
-
- public int getMaxAdvance ()
- {
- return metrics[MAX_ADVANCE];
- }
-}
diff --git a/gnu/java/awt/peer/gtk/GdkFontMetrics.java b/gnu/java/awt/peer/gtk/GdkFontMetrics.java
index c7a73a3f3..2eb0c15f8 100644
--- a/gnu/java/awt/peer/gtk/GdkFontMetrics.java
+++ b/gnu/java/awt/peer/gtk/GdkFontMetrics.java
@@ -38,33 +38,63 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Font;
-import java.awt.FontMetrics;
+import java.awt.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+
+import gnu.java.awt.ClasspathToolkit;
public class GdkFontMetrics extends FontMetrics
{
- private final int native_state = GtkGenericPeer.getUniqueInteger();
- private static final int ASCENT = 0, MAX_ASCENT = 1,
- DESCENT = 2, MAX_DESCENT = 3,
- MAX_ADVANCE = 4;
+ private int[] font_metrics;
+ GdkFontPeer peer;
+
+ static final int FONT_METRICS_ASCENT = 0;
+ static final int FONT_METRICS_MAX_ASCENT = 1;
+ static final int FONT_METRICS_DESCENT = 2;
+ static final int FONT_METRICS_MAX_DESCENT = 3;
+ static final int FONT_METRICS_MAX_ADVANCE = 4;
- private int[] metrics;
- private native int[] initState (String fname, int style, int size);
+ static final int TEXT_METRICS_X_BEARING = 0;
+ static final int TEXT_METRICS_Y_BEARING = 1;
+ static final int TEXT_METRICS_WIDTH = 2;
+ static final int TEXT_METRICS_HEIGHT = 3;
+ static final int TEXT_METRICS_X_ADVANCE = 4;
+ static final int TEXT_METRICS_Y_ADVANCE = 5;
+
+ static native void getPeerFontMetrics(GdkFontPeer peer, double [] metrics);
+ static native void getPeerTextMetrics(GdkFontPeer peer, String str, double [] metrics);
public GdkFontMetrics (Font font)
{
- super (font);
- metrics = initState (font.getName (), font.getStyle (), font.getSize ());
+ super (font.getPeer() instanceof GdkFontPeer
+ ? font
+ : ((ClasspathToolkit)(Toolkit.getDefaultToolkit ()))
+ .getFont (font.getName(), font.getAttributes ()));
+
+ peer = (GdkFontPeer) this.font.getPeer();
+
+ font_metrics = new int[5];
+ double [] hires = new double[5];
+
+ if (GtkToolkit.useGraphics2D ())
+ GdkGraphics2D.getPeerFontMetrics(peer, hires);
+ else
+ getPeerFontMetrics (peer, hires);
+
+ for (int i = 0; i < 5; ++i)
+ font_metrics[i] = (int) hires[i];
}
- native public int stringWidth (String fname, int style, int size,
- String str);
-
public int stringWidth (String str)
{
- return stringWidth (font.getName (), font.getStyle (), font.getSize (),
- str);
+ double [] hires = new double[6];
+ if (GtkToolkit.useGraphics2D())
+ GdkGraphics2D.getPeerTextMetrics(peer, str, hires);
+ else
+ getPeerTextMetrics(peer, str, hires);
+ return (int) hires [TEXT_METRICS_WIDTH];
}
public int charWidth (char ch)
@@ -77,34 +107,39 @@ public class GdkFontMetrics extends FontMetrics
return stringWidth (new String (data, off, len));
}
- // Sun's Motif implementation always returns 0 or 1 here (???).
+ /*
+ Sun's Motif implementation always returns 0 or 1 here (???), but
+ going by the X11 man pages, it seems as though we should return
+ font.ascent + font.descent.
+ */
public int getLeading ()
{
- return 0;
+ return 1;
+// return metrics[ASCENT] + metrics[DESCENT];
}
public int getAscent ()
{
- return metrics[ASCENT];
+ return font_metrics[FONT_METRICS_ASCENT];
}
public int getMaxAscent ()
{
- return metrics[MAX_ASCENT];
+ return font_metrics[FONT_METRICS_MAX_ASCENT];
}
public int getDescent ()
{
- return metrics[DESCENT];
+ return font_metrics[FONT_METRICS_DESCENT];
}
public int getMaxDescent ()
{
- return metrics[MAX_DESCENT];
+ return font_metrics[FONT_METRICS_MAX_DESCENT];
}
public int getMaxAdvance ()
{
- return metrics[MAX_ADVANCE];
+ return font_metrics[FONT_METRICS_MAX_ADVANCE];
}
}
diff --git a/gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java b/gnu/java/awt/peer/gtk/GdkFontPeer.java
index 5eeefc557..a2f61def8 100644
--- a/gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java
+++ b/gnu/java/awt/peer/gtk/GdkFontPeer.java
@@ -1,5 +1,5 @@
-/* GdkClasspathFontPeer.java -- backend implementation for Font object
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* GdkFontPeer.java -- Implements FontPeer with GTK+
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,35 +37,26 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-
+import java.awt.peer.FontPeer;
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.font.*;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.MissingResourceException;
+import java.text.CharacterIterator;
+import java.text.AttributedCharacterIterator;
+import java.text.StringCharacterIterator;
import gnu.classpath.Configuration;
import gnu.java.awt.peer.ClasspathFontPeer;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.font.GlyphVector;
-import java.awt.font.FontRenderContext;
-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.io.Serializable;
-import java.text.AttributedCharacterIterator;
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-/**
- * This class represents a windowing system font using the Pango
- * unicode/glyph/font library and the Cairo rendering library.
- *
- * @author Graydon Hoare (graydon@redhat.com)
- */
-public class GdkClasspathFontPeer extends ClasspathFontPeer
+public class GdkFontPeer extends ClasspathFontPeer
{
+
+ native static void initStaticState ();
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+ private static ResourceBundle bundle;
static
{
@@ -74,26 +65,26 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer
System.loadLibrary("gtkpeer");
}
- if (GtkToolkit.useGraphics2D ())
- initStaticState ();
- }
- native static void initStaticState ();
- private final int native_state = GtkGenericPeer.getUniqueInteger ();
+ initStaticState ();
-
- /* Instance Variables */
+ try
+ {
+ bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font");
+ }
+ catch (Throwable ignored)
+ {
+ bundle = null;
+ }
+ }
private native void initState ();
private native void dispose ();
- private native void setFont (String family, int style, int size);
-
- protected void sync ()
- {
- this.setFont (this.familyName, this.style, (int)this.size);
- }
+ private native void setFont (String family, int style, int size, boolean useGraphics2D);
protected void finalize ()
{
+ if (GtkToolkit.useGraphics2D ())
+ GdkGraphics2D.releasePeerGraphicResource (this);
dispose ();
}
@@ -133,20 +124,28 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer
/* Public API */
- public GdkClasspathFontPeer (String name, int style, int size)
+ public GdkFontPeer (String name, int style)
+ {
+ // All fonts get a default size of 12 if size is not specified.
+ this(name, style, 12);
+ }
+
+ public GdkFontPeer (String name, int style, int size)
{
super(name, style, size);
initState ();
- setFont (this.familyName, this.style, (int)this.size);
+ setFont (this.familyName, this.style, (int)this.size,
+ GtkToolkit.useGraphics2D());
}
- public GdkClasspathFontPeer (String name, Map attributes)
+ public GdkFontPeer (String name, Map attributes)
{
super(name, attributes);
initState ();
- setFont (this.familyName, this.style, (int)this.size);
+ setFont (this.familyName, this.style, (int)this.size,
+ GtkToolkit.useGraphics2D());
}
-
+
public String getSubFamilyName(Font font, Locale locale)
{
return null;
@@ -231,7 +230,6 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer
}
-
public LineMetrics getLineMetrics (Font font, CharacterIterator ci,
int begin, int limit, FontRenderContext rc)
{
@@ -291,8 +289,7 @@ public class GdkClasspathFontPeer extends ClasspathFontPeer
public FontMetrics getFontMetrics (Font font)
{
- return new GdkClasspathFontPeerMetrics (font);
+ return new GdkFontMetrics (font);
}
}
-
diff --git a/gnu/java/awt/peer/gtk/GdkGlyphVector.java b/gnu/java/awt/peer/gtk/GdkGlyphVector.java
index c811c4787..b1234b571 100644
--- a/gnu/java/awt/peer/gtk/GdkGlyphVector.java
+++ b/gnu/java/awt/peer/gtk/GdkGlyphVector.java
@@ -78,7 +78,7 @@ public class GdkGlyphVector extends GlyphVector
private Font font;
private FontRenderContext ctx;
- private native void initState (GdkClasspathFontPeer peer, FontRenderContext ctx);
+ private native void initState (GdkFontPeer peer, FontRenderContext ctx);
private native void setChars (String s);
private native void setGlyphCodes (int codes[]);
private native void dispose ();
@@ -117,7 +117,7 @@ public class GdkGlyphVector extends GlyphVector
*/
- public GdkGlyphVector (Font f, GdkClasspathFontPeer peer, FontRenderContext c, String s)
+ public GdkGlyphVector (Font f, GdkFontPeer peer, FontRenderContext c, String s)
{
font = f;
ctx = c;
@@ -125,7 +125,7 @@ public class GdkGlyphVector extends GlyphVector
setChars (s);
}
- public GdkGlyphVector (Font f, GdkClasspathFontPeer peer, FontRenderContext c, int codes[])
+ public GdkGlyphVector (Font f, GdkFontPeer peer, FontRenderContext c, int codes[])
{
font = f;
ctx = c;
diff --git a/gnu/java/awt/peer/gtk/GdkGraphics.java b/gnu/java/awt/peer/gtk/GdkGraphics.java
index 4f2ccb86c..661053bcd 100644
--- a/gnu/java/awt/peer/gtk/GdkGraphics.java
+++ b/gnu/java/awt/peer/gtk/GdkGraphics.java
@@ -284,12 +284,18 @@ public class GdkGraphics extends Graphics
native public void drawRect(int x, int y, int width, int height);
native public void fillRect (int x, int y, int width, int height);
- native void drawString (String str, int x, int y, String fname, int style, int size);
+ GdkFontPeer getFontPeer()
+ {
+ return (GdkFontPeer) getFont().getPeer();
+ }
+
+ native void drawString (GdkFontPeer f, String str, int x, int y);
public void drawString (String str, int x, int y)
{
- drawString (str, x, y, font.getName(), font.getStyle(), font.getSize());
+ drawString(getFontPeer(), str, x, y);
}
+
public void drawString (AttributedCharacterIterator ci, int x, int y)
{
throw new Error ("not implemented");
diff --git a/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/gnu/java/awt/peer/gtk/GdkGraphics2D.java
index 43fbc4b7a..8ae6a5fc5 100644
--- a/gnu/java/awt/peer/gtk/GdkGraphics2D.java
+++ b/gnu/java/awt/peer/gtk/GdkGraphics2D.java
@@ -154,7 +154,7 @@ public class GdkGraphics2D extends Graphics2D
{
paint = g.paint;
stroke = g.stroke;
- hints = g.hints;
+ setRenderingHints (g.hints);
if (g.fg.getAlpha() != -1)
fg = new Color (g.fg.getRed (), g.fg.getGreen (),
@@ -265,9 +265,6 @@ public class GdkGraphics2D extends Graphics2D
private native void cairoSave ();
private native void cairoRestore ();
private native void cairoSetMatrix (double m[]);
- private native void cairoSetFont (GdkClasspathFontPeer peer);
- private native void cairoShowGlyphs (int codes[],
- float positions[]);
private native void cairoSetOperator (int cairoOperator);
private native void cairoSetRGBColor (double red, double green, double blue);
private native void cairoSetAlpha (double alpha);
@@ -347,17 +344,23 @@ public class GdkGraphics2D extends Graphics2D
cairoRestore ();
}
+ // Some operations (drawing rather than filling) require that their
+ // coords be shifted to land on 0.5-pixel boundaries, in order to land on
+ // "middle of pixel" coordinates and light up complete pixels.
- double x;
- double y;
- private void setPos (double nx, double ny)
+ private boolean shiftDrawCalls = false;
+ private final double shifted(double coord, boolean doShift)
{
- x = nx;
- y = ny;
+ if (doShift)
+ return Math.floor(coord) + 0.5;
+ else
+ return coord;
}
- private void walkPath(PathIterator p)
+ private final void walkPath(PathIterator p, boolean doShift)
{
+ double x = 0;
+ double y = 0;
double coords[] = new double[6];
cairoSetFillRule (p.getWindingRule ());
@@ -368,13 +371,15 @@ public class GdkGraphics2D extends Graphics2D
{
case PathIterator.SEG_MOVETO:
- setPos(coords[0], coords[1]);
- cairoMoveTo (coords[0], coords[1]);
+ x = shifted(coords[0], doShift);
+ y = shifted(coords[1], doShift);
+ cairoMoveTo (x, y);
break;
case PathIterator.SEG_LINETO:
- setPos(coords[0], coords[1]);
- cairoLineTo (coords[0], coords[1]);
+ x = shifted(coords[0], doShift);
+ y = shifted(coords[1], doShift);
+ cairoLineTo (x, y);
break;
case PathIterator.SEG_QUADTO:
@@ -382,23 +387,25 @@ public class GdkGraphics2D extends Graphics2D
// splitting a quadratic bezier into a cubic:
// see: http://pfaedit.sourceforge.net/bezier.html
- double x1 = x + (2.0/3.0) * (coords[0] - x);
- double y1 = y + (2.0/3.0) * (coords[1] - y);
+ double x1 = x + (2.0/3.0) * (shifted(coords[0], doShift) - x);
+ double y1 = y + (2.0/3.0) * (shifted(coords[1], doShift) - y);
- double x2 = x1 + (1.0/3.0) * (coords[2] - x);
- double y2 = y1 + (1.0/3.0) * (coords[3] - y);
+ double x2 = x1 + (1.0/3.0) * (shifted(coords[2], doShift) - x);
+ double y2 = y1 + (1.0/3.0) * (shifted(coords[3], doShift) - y);
- setPos(coords[2], coords[3]);
+ x = shifted(coords[2], doShift);
+ y = shifted(coords[3], doShift);
cairoCurveTo (x1, y1,
x2, y2,
- coords[2], coords[3]);
+ x, y);
break;
case PathIterator.SEG_CUBICTO:
- setPos(coords[4], coords[5]);
- cairoCurveTo (coords[0], coords[1],
- coords[2], coords[3],
- coords[4], coords[5]);
+ x = shifted(coords[4], doShift);
+ y = shifted(coords[5], doShift);
+ cairoCurveTo (shifted(coords[0], doShift), shifted(coords[1], doShift),
+ shifted(coords[2], doShift), shifted(coords[3], doShift),
+ x, y);
break;
case PathIterator.SEG_CLOSE:
@@ -409,7 +416,7 @@ public class GdkGraphics2D extends Graphics2D
}
- private Map getDefaultHints()
+ private final Map getDefaultHints()
{
HashMap defaultHints = new HashMap ();
@@ -429,20 +436,22 @@ public class GdkGraphics2D extends Graphics2D
RenderingHints.VALUE_RENDER_DEFAULT);
return defaultHints;
+
}
- private void updateBufferedImage()
+ private final void updateBufferedImage()
{
int[] pixels = getImagePixels();
updateImagePixels(pixels);
}
- private boolean isBufferedImageGraphics ()
+
+ private final boolean isBufferedImageGraphics ()
{
return bimage != null;
}
- private void updateImagePixels (int[] pixels)
+ private final void updateImagePixels (int[] pixels)
{
// This function can only be used if
// this graphics object is used to draw into
@@ -475,7 +484,7 @@ public class GdkGraphics2D extends Graphics2D
}
}
- private boolean drawImage(Image img,
+ private final boolean drawImage(Image img,
AffineTransform xform,
Color bgcolor,
ImageObserver obs)
@@ -524,9 +533,8 @@ public class GdkGraphics2D extends Graphics2D
}
else
{
- // begin progressive loading in a separate thread
- new PainterThread (this, img, invertedXform, bgcolor);
- return false;
+ return this.drawImage(GdkPixbufDecoder.createBufferedImage(img.getSource()),
+ xform, bgcolor,obs);
}
}
catch (NoninvertibleTransformException e)
@@ -552,38 +560,25 @@ public class GdkGraphics2D extends Graphics2D
return;
}
- stateSave ();
cairoNewPath ();
- boolean normalize;
- normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
- || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
-
- if (normalize)
- translate (0.5,0.5);
-
if (s instanceof Rectangle2D)
{
Rectangle2D r = (Rectangle2D)s;
- cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
+ cairoRectangle (shifted(r.getX (), shiftDrawCalls),
+ shifted(r.getY (), shiftDrawCalls),
+ r.getWidth (), r.getHeight ());
}
else
- walkPath (s.getPathIterator (null));
+ walkPath (s.getPathIterator (null), shiftDrawCalls);
cairoStroke ();
- if (normalize)
- translate (-0.5,-0.5);
-
- stateRestore ();
-
if (isBufferedImageGraphics ())
updateBufferedImage();
-
}
public void fill (Shape s)
{
- stateSave();
cairoNewPath ();
if (s instanceof Rectangle2D)
{
@@ -591,9 +586,8 @@ public class GdkGraphics2D extends Graphics2D
cairoRectangle (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
}
else
- walkPath (s.getPathIterator (null));
+ walkPath (s.getPathIterator (null), false);
cairoFill ();
- stateRestore ();
if (isBufferedImageGraphics ())
updateBufferedImage();
@@ -627,8 +621,8 @@ public class GdkGraphics2D extends Graphics2D
r.getWidth (), r.getHeight ());
}
else
- walkPath (clip.getPathIterator (null));
- cairoClosePath ();
+ walkPath (clip.getPathIterator (null), false);
+ // cairoClosePath ();
cairoClip ();
}
}
@@ -774,7 +768,7 @@ public class GdkGraphics2D extends Graphics2D
{
BasicStroke bs = (BasicStroke) stroke;
cairoSetLineCap (bs.getEndCap());
- cairoSetLineWidth (bs.getLineWidth() / 2.0);
+ cairoSetLineWidth (bs.getLineWidth());
cairoSetLineJoin (bs.getLineJoin());
cairoSetMiterLimit (bs.getMiterLimit());
float dashes[] = bs.getDashArray();
@@ -877,96 +871,34 @@ public class GdkGraphics2D extends Graphics2D
r.getWidth (), r.getHeight ());
}
else
- walkPath (s.getPathIterator (null));
- cairoClosePath ();
+ walkPath (s.getPathIterator (null), false);
+ // cairoClosePath ();
cairoClip ();
}
}
+ private static BasicStroke draw3DRectStroke = new BasicStroke();
+
public void draw3DRect(int x, int y, int width,
int height, boolean raised)
{
- Color std = fg;
- Color light = std.brighter();
- Color dark = std.darker();
-
- if (!raised)
- {
- Color t = light;
- light = dark;
- dark = t;
- }
-
- double x1 = (double) x;
- double x2 = (double) x + width;
-
- double y1 = (double) y;
- double y2 = (double) y + height;
-
- stateSave ();
-
- cairoNewPath ();
-
- boolean normalize;
- normalize = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
- || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
-
- if (normalize)
- {
- x1 += 0.5;
- y1 += 0.5;
- x2 += 0.5;
- y2 += 0.5;
- }
-
- setColor (light);
- cairoMoveTo (x1, y1);
- cairoLineTo (x2, y1);
- cairoLineTo (x2, y2);
- cairoStroke ();
-
- cairoNewPath ();
- setColor (dark);
- cairoMoveTo (x1, y1);
- cairoLineTo (x1, y2);
- cairoLineTo (x2, y2);
- cairoStroke ();
-
- stateRestore ();
-
+ Stroke tmp = stroke;
+ setStroke(draw3DRectStroke);
+ super.draw3DRect(x, y, width, height, raised);
+ setStroke(tmp);
if (isBufferedImageGraphics ())
updateBufferedImage();
-
}
public void fill3DRect(int x, int y, int width,
int height, boolean raised)
{
- double step = 1.0;
- if (stroke != null && stroke instanceof BasicStroke)
- {
- BasicStroke bs = (BasicStroke) stroke;
- step = bs.getLineWidth();
- }
-
- Color bright = fg.brighter ();
- Color dark = fg.darker ();
-
- draw3DRect (x, y, width, height, raised);
-
- stateSave ();
- translate (step/2.0, step/2.0);
- cairoNewPath ();
- cairoRectangle ((double) x, (double) y,
- ((double) width) - step,
- ((double) height) - step );
- cairoClosePath ();
- cairoFill ();
- stateRestore ();
-
+ Stroke tmp = stroke;
+ setStroke(draw3DRectStroke);
+ super.fill3DRect(x, y, width, height, raised);
+ setStroke(tmp);
if (isBufferedImageGraphics ())
updateBufferedImage();
-
}
@@ -977,21 +909,21 @@ public class GdkGraphics2D extends Graphics2D
public void fillRect (int x, int y, int width, int height)
{
- fill(new Rectangle (x, y, width, height));
+ cairoNewPath ();
+ cairoRectangle (x, y, width, height);
+ cairoFill ();
}
public void clearRect (int x, int y, int width, int height)
{
- stateSave ();
cairoSetRGBColor (bg.getRed() / 255.0,
bg.getGreen() / 255.0,
bg.getBlue() / 255.0);
cairoSetAlpha (1.0);
cairoNewPath ();
cairoRectangle (x, y, width, height);
- cairoClosePath ();
cairoFill ();
- stateRestore ();
+ setColor (fg);
if (isBufferedImageGraphics ())
updateBufferedImage();
@@ -1008,7 +940,7 @@ public class GdkGraphics2D extends Graphics2D
return bg;
}
- private void doPolygon(int[] xPoints, int[] yPoints, int nPoints,
+ private final void doPolygon(int[] xPoints, int[] yPoints, int nPoints,
boolean close, boolean fill)
{
if (nPoints < 1)
@@ -1064,7 +996,7 @@ public class GdkGraphics2D extends Graphics2D
doPolygon (xPoints, yPoints, nPoints, false, false);
}
- private boolean drawRaster (ColorModel cm, Raster r,
+ private final boolean drawRaster (ColorModel cm, Raster r,
AffineTransform imageToUser,
Color bgcolor)
{
@@ -1125,10 +1057,7 @@ public class GdkGraphics2D extends Graphics2D
}
}
- stateSave ();
- translate (x, y);
drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth (), i2u);
- stateRestore ();
if (isBufferedImageGraphics ())
updateBufferedImage();
@@ -1171,113 +1100,6 @@ public class GdkGraphics2D extends Graphics2D
}
- ////////////////////////////////////////
- ////// Supporting Private Classes //////
- ////////////////////////////////////////
-
- private class PainterThread implements Runnable, ImageConsumer
- {
-
- // this is a helper which is spun off when someone tries to do
- // Graphics2D.drawImage on an image we cannot determine to be either
- // one of our own offscreen images or a BufferedImage; that is, when
- // someone wants to draw an image which is possibly still loading over
- // a network or something. you run it in a separate thread and it
- // writes through to the underlying Graphics2D as pixels becomg
- // available.
-
- GdkGraphics2D gr;
- Image image;
- ColorModel defaultModel;
- AffineTransform xform;
- Color bgcolor;
-
- public PainterThread (GdkGraphics2D g, Image im,
- AffineTransform xf, Color bg)
- {
- image = im;
- xform = xf;
- bgcolor = bg;
- this.gr = (GdkGraphics2D) g.create ();
- new Thread (this).start ();
- }
-
- public void imageComplete (int status)
- {
- }
-
- public void setColorModel (ColorModel model)
- {
- defaultModel = model;
- }
-
- public void setDimensions (int width, int height)
- {
- }
-
- public void setHints (int hintflags)
- {
- }
-
- public void setPixels (int x, int y, int w, int h, ColorModel model,
- byte[] pixels, int off, int scansize)
- {
- }
-
- public void setPixels (int x, int y, int w, int h, ColorModel model,
- int[] pixels, int off, int scansize)
- {
- gr.stateSave ();
- gr.translate (x, y);
-
- if (model == null)
- model = defaultModel;
-
- int pixels2[];
- if (model != null)
- {
- pixels2 = new int[pixels.length];
- for (int yy = 0; yy < h; yy++)
- for (int xx = 0; xx < w; xx++)
- {
- int i = yy * scansize + xx;
- pixels2[i] = model.getRGB (pixels[i]);
- }
- }
- else
- pixels2 = pixels;
-
- // change all transparent pixels in the image to the
- // specified bgcolor
-
- if (bgcolor != null)
- {
- for (int i = 0; i < pixels2.length; i++)
- {
- if (model.getAlpha (pixels2[i]) == 0)
- pixels2[i] = bgcolor.getRGB ();
- }
- }
-
- double[] xf = new double[6];
- xform.getMatrix(xf);
- gr.drawPixels (pixels2, w, h, scansize, xf);
- gr.stateRestore ();
- }
-
- public void setProperties (java.util.Hashtable props)
- {
- }
-
- public void run ()
- {
- image.getSource ().startProduction (this);
- gr.dispose ();
- }
- }
-
-
-
///////////////////////////////////////////////
////// Unimplemented Stubs and Overloads //////
///////////////////////////////////////////////
@@ -1339,6 +1161,9 @@ public class GdkGraphics2D extends Graphics2D
}
+ shiftDrawCalls = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
+ || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
+
}
public Object getRenderingHint(RenderingHints.Key hintKey)
@@ -1371,6 +1196,9 @@ public class GdkGraphics2D extends Graphics2D
else if(hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT))
cairoSurfaceSetFilter(4);
}
+
+ shiftDrawCalls = hints.containsValue (RenderingHints.VALUE_STROKE_NORMALIZE)
+ || hints.containsValue (RenderingHints.VALUE_STROKE_DEFAULT);
}
public void addRenderingHints(Map hints)
@@ -1396,23 +1224,6 @@ public class GdkGraphics2D extends Graphics2D
return new FontRenderContext (transform, true, true);
}
- public void drawGlyphVector (GlyphVector g, float x, float y)
- {
- stateSave ();
- setFont (g.getFont ());
- translate ((double)x, (double)y);
- cairoMoveTo (0, 0);
- int nglyphs = g.getNumGlyphs ();
- int codes[] = g.getGlyphCodes (0, nglyphs, (int []) null);
- float posns[] = g.getGlyphPositions (0, nglyphs, (float []) null);
- cairoShowGlyphs (codes, posns);
-
- if (isBufferedImageGraphics ())
- updateBufferedImage();
-
- stateRestore ();
- }
-
public void copyArea (int x, int y, int width, int height, int dx, int dy)
{
throw new java.lang.UnsupportedOperationException ();
@@ -1544,15 +1355,40 @@ public class GdkGraphics2D extends Graphics2D
drawLine (x1, y + height, x2, y + height);
}
- public void drawString (String str, int x, int y)
+ // these are the most accelerated painting paths
+ native void cairoDrawGdkGlyphVector (GdkFontPeer f, GdkGlyphVector gv, float x, float y);
+ native void cairoDrawGdkTextLayout (GdkFontPeer f, GdkTextLayout gl, float x, float y);
+ native void cairoDrawString (GdkFontPeer f, String str, float x, float y);
+
+ GdkFontPeer getFontPeer()
{
- drawString (str, (float)x, (float)y);
+ return (GdkFontPeer) getFont().getPeer();
+ }
+
+ public void drawGdkGlyphVector(GdkGlyphVector gv, float x, float y)
+ {
+ cairoDrawGdkGlyphVector(getFontPeer(), gv, x, y);
+ if (isBufferedImageGraphics ())
+ updateBufferedImage();
+ }
+
+ public void drawGdkTextLayout(GdkTextLayout gl, float x, float y)
+ {
+ cairoDrawGdkTextLayout(getFontPeer(), gl, x, y);
+ if (isBufferedImageGraphics ())
+ updateBufferedImage();
}
public void drawString (String str, float x, float y)
{
- GlyphVector gv = font.createGlyphVector (getFontRenderContext(), str);
- drawGlyphVector (gv, x, y);
+ cairoDrawString(getFontPeer(), str, x, y);
+ if (isBufferedImageGraphics ())
+ updateBufferedImage();
+ }
+
+ public void drawString (String str, int x, int y)
+ {
+ drawString (str, (float)x, (float)y);
}
public void drawString (AttributedCharacterIterator ci, int x, int y)
@@ -1560,6 +1396,14 @@ public class GdkGraphics2D extends Graphics2D
drawString (ci, (float)x, (float)y);
}
+ public void drawGlyphVector (GlyphVector gv, float x, float y)
+ {
+ if (gv instanceof GdkGlyphVector)
+ drawGdkGlyphVector((GdkGlyphVector)gv, x, y);
+ else
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
public void drawString (AttributedCharacterIterator ci, float x, float y)
{
GlyphVector gv = font.createGlyphVector (getFontRenderContext(), ci);
@@ -1605,28 +1449,36 @@ public class GdkGraphics2D extends Graphics2D
return font;
}
+ // Until such time as pango is happy to talk directly to cairo, we
+ // actually need to redirect some calls from the GtkFontPeer and
+ // GtkFontMetrics into the drawing kit and ask cairo ourselves.
+
+ static native void releasePeerGraphicResource (GdkFontPeer f);
+ static native void getPeerTextMetrics (GdkFontPeer f, String str, double [] metrics);
+ static native void getPeerFontMetrics (GdkFontPeer f, double [] metrics);
+
public FontMetrics getFontMetrics ()
{
+ // the reason we go via the toolkit here is to try to get
+ // a cached object. the toolkit keeps such a cache.
return Toolkit.getDefaultToolkit ().getFontMetrics (font);
}
public FontMetrics getFontMetrics (Font f)
{
+ // the reason we go via the toolkit here is to try to get
+ // a cached object. the toolkit keeps such a cache.
return Toolkit.getDefaultToolkit ().getFontMetrics (f);
}
public void setFont (Font f)
{
- if (f.getPeer() instanceof GdkClasspathFontPeer)
+ if (f.getPeer() instanceof GdkFontPeer)
font = f;
else
font =
((ClasspathToolkit)(Toolkit.getDefaultToolkit ()))
.getFont (f.getName(), f.getAttributes ());
-
- if (f != null &&
- f.getPeer() instanceof GdkClasspathFontPeer)
- cairoSetFont ((GdkClasspathFontPeer) f.getPeer());
}
public String toString()
diff --git a/gnu/java/awt/peer/gtk/GdkTextLayout.java b/gnu/java/awt/peer/gtk/GdkTextLayout.java
new file mode 100644
index 000000000..26cfc16f0
--- /dev/null
+++ b/gnu/java/awt/peer/gtk/GdkTextLayout.java
@@ -0,0 +1,435 @@
+/* GdkTextLayout.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., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 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.Graphics2D;
+import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphMetrics;
+import java.awt.font.GlyphVector;
+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.CharacterIterator;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.Map;
+import java.awt.font.TextAttribute;
+
+import gnu.classpath.Configuration;
+import gnu.java.awt.peer.ClasspathTextLayoutPeer;
+
+/**
+ * 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
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("gtkpeer");
+ }
+ initStaticState ();
+ }
+ private native void setText(String str);
+ private native void getExtents(double[] inkExtents,
+ double[] logExtents);
+ private native void indexToPos(int idx, double[] pos);
+ private native void initState ();
+ private native void dispose ();
+ native static 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;
+ }
+
+ 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)
+ {
+ if (g2 instanceof GdkGraphics2D)
+ {
+ // we share pango structures directly with GdkGraphics2D
+ // when legal
+ GdkGraphics2D gg2 = (GdkGraphics2D) g2;
+ gg2.drawGdkTextLayout(this, x, y);
+ }
+ else
+ {
+ // falling back to a rather tedious layout algorithm when
+ // not legal
+ AttributedCharacterIterator ci = attributedString.getIterator ();
+ CharacterIteratorProxy proxy = new CharacterIteratorProxy (ci);
+ Font defFont = g2.getFont ();
+
+ /* Note: this implementation currently only interprets FONT text
+ * attributes. There is a reasonable argument to be made for some
+ * attributes being interpreted out here, where we have control of the
+ * Graphics2D and can construct or derive new fonts, and some
+ * attributes being interpreted by the GlyphVector itself. So far, for
+ * all attributes except FONT we do neither.
+ */
+
+ for (char c = ci.first ();
+ c != CharacterIterator.DONE;
+ c = ci.next ())
+ {
+ proxy.begin = ci.getIndex ();
+ proxy.limit = ci.getRunLimit(TextAttribute.FONT);
+ if (proxy.limit <= proxy.begin)
+ continue;
+
+ proxy.index = proxy.begin;
+
+ Object fnt = ci.getAttribute(TextAttribute.FONT);
+ GlyphVector gv;
+ if (fnt instanceof Font)
+ gv = ((Font)fnt).createGlyphVector (fontRenderContext, proxy);
+ else
+ gv = defFont.createGlyphVector (fontRenderContext, proxy);
+
+ g2.drawGlyphVector (gv, x, y);
+
+ int n = gv.getNumGlyphs ();
+ for (int i = 0; i < n; ++i)
+ {
+ GlyphMetrics gm = gv.getGlyphMetrics (i);
+ if (gm.getAdvanceX() == gm.getAdvance ())
+ x += gm.getAdvanceX ();
+ else
+ y += gm.getAdvanceY ();
+ }
+ }
+ }
+ }
+
+ 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 Shape getOutline (AffineTransform tx)
+ {
+ throw new Error("not implemented");
+ }
+
+ 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/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
index e4e4f08f4..b4507643e 100644
--- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
@@ -224,7 +224,7 @@ public class GtkComponentPeer extends GtkGenericPeer
public FontMetrics getFontMetrics (Font font)
{
- return new GdkFontMetrics (font);
+ return getToolkit().getFontMetrics(font);
}
public Graphics getGraphics ()
diff --git a/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
index 651118d84..94874deb6 100644
--- a/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
@@ -68,11 +68,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer
awtComponent.setFont (f);
}
- FontMetrics fm;
- if (GtkToolkit.useGraphics2D ())
- fm = new GdkClasspathFontPeerMetrics (f);
- else
- fm = new GdkFontMetrics (f);
+ FontMetrics fm = getFontMetrics (f);
TextArea ta = ((TextArea) awtComponent);
int sizeRows = ta.getRows ();
@@ -130,11 +126,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer
if (f == null)
return new Dimension (width, height);
- FontMetrics fm;
- if (GtkToolkit.useGraphics2D ())
- fm = new GdkClasspathFontPeerMetrics (f);
- else
- fm = new GdkFontMetrics (f);
+ FontMetrics fm = getFontMetrics (f);
int sizeRows = rows == 0 ? DEFAULT_ROWS : rows;
int sizeCols = cols == 0 ? DEFAULT_COLS : cols;
@@ -163,11 +155,7 @@ public class GtkTextAreaPeer extends GtkTextComponentPeer
if (f == null)
return new Dimension (width, height);
- FontMetrics fm;
- if (GtkToolkit.useGraphics2D ())
- fm = new GdkClasspathFontPeerMetrics (f);
- else
- fm = new GdkFontMetrics (f);
+ FontMetrics fm = getFontMetrics (f);
int sizeRows = rows == 0 ? DEFAULT_ROWS : rows;
int sizeCols = cols == 0 ? DEFAULT_COLS : cols;
diff --git a/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java b/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
index 73d92cbaa..bd1ac8124 100644
--- a/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
@@ -66,11 +66,7 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer
awtComponent.setFont (f);
}
- FontMetrics fm;
- if (GtkToolkit.useGraphics2D ())
- fm = new GdkClasspathFontPeerMetrics (f);
- else
- fm = new GdkFontMetrics (f);
+ FontMetrics fm = getFontMetrics (f);
TextField tf = ((TextField) awtComponent);
int cols = tf.getColumns ();
@@ -117,11 +113,7 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer
if (f == null)
return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]);
- FontMetrics fm;
- if (GtkToolkit.useGraphics2D ())
- fm = new GdkClasspathFontPeerMetrics (f);
- else
- fm = new GdkFontMetrics (f);
+ FontMetrics fm = getFontMetrics (f);
int text_width = cols * fm.getMaxAdvance ();
@@ -140,11 +132,7 @@ public class GtkTextFieldPeer extends GtkTextComponentPeer
if (f == null)
return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]);
- FontMetrics fm;
- if (GtkToolkit.useGraphics2D ())
- fm = new GdkClasspathFontPeerMetrics (f);
- else
- fm = new GdkFontMetrics (f);
+ FontMetrics fm = getFontMetrics (f);
int text_width = cols * fm.getMaxAdvance ();
diff --git a/gnu/java/awt/peer/gtk/GtkToolkit.java b/gnu/java/awt/peer/gtk/GtkToolkit.java
index 277200b51..bfb9cc908 100644
--- a/gnu/java/awt/peer/gtk/GtkToolkit.java
+++ b/gnu/java/awt/peer/gtk/GtkToolkit.java
@@ -42,6 +42,7 @@ import gnu.classpath.Configuration;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.EmbeddedWindowSupport;
import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.ClasspathTextLayoutPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
import gnu.java.awt.peer.gtk.GdkPixbufDecoder;
@@ -49,6 +50,7 @@ import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.awt.im.InputMethodHighlight;
import java.awt.image.BufferedImage;
@@ -58,6 +60,8 @@ import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.peer.*;
import java.net.URL;
+import java.text.AttributedString;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
@@ -302,22 +306,59 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
"SansSerif" });
}
+ private class LRUCache extends java.util.LinkedHashMap
+ {
+ int max_entries;
+ public LRUCache(int max)
+ {
+ super(max, 0.75f, true);
+ max_entries = max;
+ }
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ {
+ return size() > max_entries;
+ }
+ }
+
+ private LRUCache fontCache = new LRUCache(50);
+ private LRUCache metricsCache = new LRUCache(50);
+ private LRUCache imageCache = new LRUCache(50);
+
public FontMetrics getFontMetrics (Font font)
{
- if (useGraphics2D())
- return new GdkClasspathFontPeerMetrics (font);
+ if (metricsCache.containsKey(font))
+ return (FontMetrics) metricsCache.get(font);
else
- return new GdkFontMetrics (font);
+ {
+ FontMetrics m;
+ m = new GdkFontMetrics (font);
+ metricsCache.put(font, m);
+ return m;
+ }
}
public Image getImage (String filename)
{
- return createImage (filename);
+ if (imageCache.containsKey(filename))
+ return (Image) imageCache.get(filename);
+ else
+ {
+ Image im = createImage(filename);
+ imageCache.put(filename, im);
+ return im;
+ }
}
public Image getImage (URL url)
{
- return createImage (url);
+ if (imageCache.containsKey(url))
+ return (Image) imageCache.get(url);
+ else
+ {
+ Image im = createImage(url);
+ imageCache.put(url, im);
+ return im;
+ }
}
public PrintJob getPrintJob (Frame frame, String jobtitle, Properties props)
@@ -508,8 +549,10 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
*/
private FontPeer getFontPeer (String name, int style, int size)
{
- GtkFontPeer fp = new GtkFontPeer (name, style, size);
- return fp;
+ Map attrs = new HashMap ();
+ ClasspathFontPeer.copyStyleToAttrs (style, attrs);
+ ClasspathFontPeer.copySizeToAttrs (size, attrs);
+ return getClasspathFontPeer (name, attrs);
}
/**
@@ -520,38 +563,26 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
public ClasspathFontPeer getClasspathFontPeer (String name, Map attrs)
{
- if (useGraphics2D())
- return new GdkClasspathFontPeer (name, attrs);
+ Map keyMap = new HashMap (attrs);
+ // We don't know what kind of "name" the user requested (logical, face,
+ // family), and we don't actually *need* to know here. The worst case
+ // involves failure to consolidate fonts with the same backend in our
+ // cache. This is harmless.
+ keyMap.put ("GtkToolkit.RequestedFontName", name);
+ if (fontCache.containsKey (keyMap))
+ return (ClasspathFontPeer) fontCache.get (keyMap);
else
{
- // Default values
- int size = 12;
- int style = Font.PLAIN;
- if (name == null)
- name = "Default";
-
- if (attrs.containsKey (TextAttribute.WEIGHT))
- {
- Float weight = (Float) attrs.get (TextAttribute.WEIGHT);
- if (weight.floatValue () >= TextAttribute.WEIGHT_BOLD.floatValue ())
- style += Font.BOLD;
+ ClasspathFontPeer newPeer = new GdkFontPeer (name, attrs);
+ fontCache.put (keyMap, newPeer);
+ return newPeer;
}
-
- if (attrs.containsKey (TextAttribute.POSTURE))
- {
- Float posture = (Float) attrs.get (TextAttribute.POSTURE);
- if (posture.floatValue () >= TextAttribute.POSTURE_OBLIQUE.floatValue ())
- style += Font.ITALIC;
}
- if (attrs.containsKey (TextAttribute.SIZE))
+ public ClasspathTextLayoutPeer getClasspathTextLayoutPeer (AttributedString str,
+ FontRenderContext frc)
{
- Float fsize = (Float) attrs.get (TextAttribute.SIZE);
- size = fsize.intValue();
- }
-
- return (ClasspathFontPeer) this.getFontPeer (name, style, size);
- }
+ return new GdkTextLayout(str, frc);
}
protected EventQueue getSystemEventQueueImpl()