diff options
Diffstat (limited to 'gnu/java')
| -rw-r--r-- | gnu/java/awt/ClasspathToolkit.java | 6 | ||||
| -rw-r--r-- | gnu/java/awt/peer/ClasspathFontPeer.java | 4 | ||||
| -rw-r--r-- | gnu/java/awt/peer/ClasspathTextLayoutPeer.java | 111 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GdkClasspathFontPeerMetrics.java | 119 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GdkFontMetrics.java | 79 | ||||
| -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.java | 6 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GdkGraphics.java | 10 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GdkGraphics2D.java | 392 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GdkTextLayout.java | 435 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GtkComponentPeer.java | 2 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GtkTextAreaPeer.java | 18 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GtkTextFieldPeer.java | 18 | ||||
| -rw-r--r-- | gnu/java/awt/peer/gtk/GtkToolkit.java | 97 |
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() |
