From c768f6ecd4c053662755ce4f402c8a03edcfce28 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Tue, 21 Nov 2006 14:14:25 +0000 Subject: 2006-11-21 Roman Kennke * gnu/java/awt/peer/gtk/GdkFontMetrics.java: Removed. This is now an inner class in GdkFontPeer. * gnu/java/awt/peer/gtk/CairoGraphics2D.java (drawString(float,float)): Use text layout cache from GdkFontPeer. (getFontMetrics): Delegate to GdkFontPeer. * gnu/java/awt/peer/gtk/FreetypeGlyphVector.java (getGlyphCodes): Also check array size. (getGlyphPositions): Also check array size. * gnu/java/awt/peer/gtk/GdkFontPeer.java (GdkFontLineMetrics.fm): Removed. (GdkFontLineMetrics.strikeThroughOffset): Removed. (GdkFontLineMetrics.strikeThroughThickness): Removed. (GdkFontLineMetrics.underlineOffset): Removed. (GdkFontLineMetrics.underlineThickness): Removed. (GdkFontLineMetrics.GdkFontLineMetrics): Don't take FontMetrics argument. Don't init removed fields. (GdkFontLineMetrics.getAscent): Return font peer's field. (GdkFontLineMetrics.getDescent): Return font peer's field. (GdkFontLineMetrics.getHeight): Return font peer's field. (GdkFontLineMetrics.getLeading): Return font peer's field. (GdkFontLineMetrics.getNumChars): Reformat. (GdkFontLineMetrics.getStrikeThroughOffset): Return half ascent. (GdkFontLineMetrics.getStrikeThroughThickness): Return 1. (GdkFontLineMetrics.getUnderlineOffset): Return font peer's field. (GdkFontLineMetrics.getUnderlineThickness): Return font peer's field. (GdkFontMetrics): Moved class in here as inner class. Make it use the font peer's fields and for the char(s) width and string width method, use TextLayout to measure the actual widths. (ascent): New field. (bundle): Removed. (DEFAULT_CTX): New constant field. (descent): New field. (FONT_METRICS_ASCENT): New constant. (FONT_METRICS_DESCENT): New constant. (FONT_METRICS_HEIGHT): New constant. (FONT_METRICS_MAX_ADVANCE): New constant. (FONT_METRICS_MAX_ASCENT): New constant. (FONT_METRICS_MAX_DESCENT): New constant. (FONT_METRICS_UNDERLINE_OFFSET): New constant. (FONT_METRICS_UNDERLINE_THICKNESS): New constant. (height): New field. (maxAdvance): New field. (maxAscent): New field. (maxDescent): New field. (metrics): New field. Stores a FontMetrics for this font. (textLayoutCache): New field. Caches TextLayout instances. (underlineOffset): New field. (underlineThickness): New field. (cinit): Don't initialize resource bundle. (GdkFontPeer): Setup the metrics. (getFontMetrics): Return stored metrics if possible. (getLineMetrics): Adapt to new constructor. (initFont): New helper method. (setupMetrics): New helper method. * gnu/java/awt/peer/gtk/GtkToolkit.java (LRUCache): Made class a static class. (getFontMetrics): Delegate to GdkFontPeer. * native/jni/gtk-peer/gdkfont.h Added new constant defines. * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c (getFontMetrics): Rewritten to fetch the font metrics from FreeType. --- gnu/java/awt/peer/gtk/CairoGraphics2D.java | 14 +- gnu/java/awt/peer/gtk/FreetypeGlyphVector.java | 4 +- gnu/java/awt/peer/gtk/GdkFontMetrics.java | 157 ------------------ gnu/java/awt/peer/gtk/GdkFontPeer.java | 213 ++++++++++++++++++++----- gnu/java/awt/peer/gtk/GtkToolkit.java | 17 +- 5 files changed, 189 insertions(+), 216 deletions(-) delete mode 100644 gnu/java/awt/peer/gtk/GdkFontMetrics.java (limited to 'gnu/java') diff --git a/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java index ce3041d73..68ada66fb 100644 --- a/gnu/java/awt/peer/gtk/CairoGraphics2D.java +++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java @@ -1523,8 +1523,14 @@ public abstract class CairoGraphics2D extends Graphics2D { if (str == null || str.length() == 0) return; - (new TextLayout( str, getFont(), getFontRenderContext() )). - draw(this, x, y); + GdkFontPeer fontPeer = (GdkFontPeer) font.getPeer(); + TextLayout tl = (TextLayout) fontPeer.textLayoutCache.get(str); + if (tl == null) + { + tl = new TextLayout( str, getFont(), getFontRenderContext() ); + fontPeer.textLayoutCache.put(str, tl); + } + tl.draw(this, x, y); } public void drawString(String str, int x, int y) @@ -1593,9 +1599,7 @@ public abstract class CairoGraphics2D extends Graphics2D 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); + return ((GdkFontPeer) f.getPeer()).getFontMetrics(f); } public void setFont(Font f) diff --git a/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java index 98f1bd69b..4ad87a84b 100644 --- a/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java +++ b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java @@ -294,7 +294,7 @@ public class FreetypeGlyphVector extends GlyphVector { int[] rval; - if( codeReturn == null ) + if( codeReturn == null || codeReturn.length < numEntries) rval = new int[ numEntries ]; else rval = codeReturn; @@ -395,7 +395,7 @@ public class FreetypeGlyphVector extends GlyphVector public float[] getGlyphPositions(int beginGlyphIndex, int numEntries, float[] positionReturn) { - if (positionReturn == null) + if (positionReturn == null || positionReturn.length < (numEntries * 2)) positionReturn = new float[numEntries*2]; System.arraycopy(glyphPositions, beginGlyphIndex*2, positionReturn, 0, diff --git a/gnu/java/awt/peer/gtk/GdkFontMetrics.java b/gnu/java/awt/peer/gtk/GdkFontMetrics.java deleted file mode 100644 index 30b1ff15e..000000000 --- a/gnu/java/awt/peer/gtk/GdkFontMetrics.java +++ /dev/null @@ -1,157 +0,0 @@ -/* GdkFontMetrics.java - Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.java.awt.peer.gtk; - -import gnu.java.awt.ClasspathToolkit; - -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Toolkit; - -public class GdkFontMetrics extends FontMetrics -{ - - 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; - - 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; - - /** - * Makes sure to return a Font based on the given Font that has as - * peer a GdkFontPeer. Used in the initializer. - */ - private static Font initFont(Font font) - { - if (font == null) - return new Font("Dialog", Font.PLAIN, 12); - else if (font.getPeer() instanceof GdkFontPeer) - return font; - else - { - ClasspathToolkit toolkit; - toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit(); - return toolkit.getFont(font.getName(), font.getAttributes()); - } - } - - public GdkFontMetrics (Font font) - { - super(initFont(font)); - peer = (GdkFontPeer) this.font.getPeer(); - - font_metrics = new int[5]; - double [] hires = new double[5]; - peer.getFontMetrics (hires); - for (int i = 0; i < 5; ++i) - font_metrics[i] = (int) hires[i]; - } - - public int stringWidth (String str) - { - -// TextLayout layout = new TextLayout(str, getFont(), null); -// return (int) layout.getAdvance(); - // We need to filter control chars, because they are never displayed - // in Java and thus also have no metrics. - int len = str.length(); - StringBuilder b = new StringBuilder(len); - for (int i = 0; i < len; i++) - { - char ch = str.charAt(i); - if (! Character.isISOControl(ch)) - b.append(ch); - } - double [] hires = new double[6]; - String string = b.toString(); - peer.getTextMetrics(string, hires); - return (int) hires [TEXT_METRICS_WIDTH]; - } - - 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)); - } - - public int getLeading () - { - // Sun always returns 0. - return 0; - } - - public int getAscent () - { - return font_metrics[FONT_METRICS_ASCENT]; - } - - public int getMaxAscent () - { - return font_metrics[FONT_METRICS_MAX_ASCENT]; - } - - public int getDescent () - { - return font_metrics[FONT_METRICS_DESCENT]; - } - - public int getMaxDescent () - { - return font_metrics[FONT_METRICS_MAX_DESCENT]; - } - - public int getMaxAdvance () - { - return font_metrics[FONT_METRICS_MAX_ADVANCE]; - } -} diff --git a/gnu/java/awt/peer/gtk/GdkFontPeer.java b/gnu/java/awt/peer/gtk/GdkFontPeer.java index 40b234984..28975991b 100644 --- a/gnu/java/awt/peer/gtk/GdkFontPeer.java +++ b/gnu/java/awt/peer/gtk/GdkFontPeer.java @@ -38,6 +38,7 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; +import gnu.java.awt.ClasspathToolkit; import gnu.java.awt.peer.ClasspathFontPeer; import gnu.java.awt.font.opentype.NameDecoder; @@ -48,39 +49,125 @@ import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.font.GlyphMetrics; import java.awt.font.LineMetrics; +import java.awt.font.TextLayout; import java.awt.geom.Rectangle2D; import java.text.CharacterIterator; import java.util.Locale; import java.util.Map; -import java.util.ResourceBundle; import java.nio.ByteBuffer; import java.util.HashMap; public class GdkFontPeer extends ClasspathFontPeer { + static final FontRenderContext DEFAULT_CTX = + new FontRenderContext(null, false, false); + + /** + * Caches TextLayout instances for use in charsWidth() and drawString(). + * The size of the cache has been chosen so that relativly large GUIs with + * text documents are still efficient. + */ + HashMap textLayoutCache = new GtkToolkit.LRUCache(500); + + private class GdkFontMetrics extends FontMetrics + { + + public GdkFontMetrics (Font font) + { + super(initFont(font)); + } + + public int stringWidth (String str) + { + TextLayout tl = (TextLayout) textLayoutCache.get(str); + if (tl == null) + { + tl = new TextLayout(str, font, DEFAULT_CTX); + textLayoutCache.put(str, tl); + } + return (int) tl.getAdvance(); + } + + 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)); + } + + public int getHeight() + { + return (int) height; + } + + public int getLeading () + { + return (int) (height - (ascent + descent)); + } + + public int getAscent () + { + return (int) ascent; + } + + public int getMaxAscent () + { + return (int) ascent; + } + + public int getDescent () + { + return (int) descent; + } + + public int getMaxDescent () + { + return (int) maxDescent; + } + + public int getMaxAdvance () + { + return (int) maxAdvance; + } + } + static native void initStaticState(); private final int native_state = GtkGenericPeer.getUniqueInteger (); - private static ResourceBundle bundle; /** * Cache GlyphMetrics objects. */ private HashMap metricsCache; - + + private static final int FONT_METRICS_ASCENT = 0; + private static final int FONT_METRICS_MAX_ASCENT = 1; + private static final int FONT_METRICS_DESCENT = 2; + private static final int FONT_METRICS_MAX_DESCENT = 3; + private static final int FONT_METRICS_MAX_ADVANCE = 4; + private static final int FONT_METRICS_HEIGHT = 5; + private static final int FONT_METRICS_UNDERLINE_OFFSET = 6; + private static final int FONT_METRICS_UNDERLINE_THICKNESS = 7; + + float ascent; + float descent; + float maxAscent; + float maxDescent; + float maxAdvance; + float height; + float underlineOffset; + float underlineThickness; + + GdkFontMetrics metrics; + static { System.loadLibrary("gtkpeer"); initStaticState (); - try - { - bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font"); - } - catch (Throwable ignored) - { - bundle = null; - } } private ByteBuffer nameTable = null; @@ -149,6 +236,7 @@ public class GdkFontPeer extends ClasspathFontPeer initState (); setFont (this.familyName, this.style, (int)this.size); metricsCache = new HashMap(); + setupMetrics(); } public GdkFontPeer (String name, Map attributes) @@ -157,6 +245,40 @@ public class GdkFontPeer extends ClasspathFontPeer initState (); setFont (this.familyName, this.style, (int)this.size); metricsCache = new HashMap(); + setupMetrics(); + } + + + /** + * Makes sure to return a Font based on the given Font that has as + * peer a GdkFontPeer. Used in the initializer. + */ + static Font initFont(Font font) + { + if (font == null) + return new Font("Dialog", Font.PLAIN, 12); + else if (font.getPeer() instanceof GdkFontPeer) + return font; + else + { + ClasspathToolkit toolkit; + toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit(); + return toolkit.getFont(font.getName(), font.getAttributes()); + } + } + + private void setupMetrics() + { + double [] hires = new double[8]; + getFontMetrics(hires); + ascent = (float) hires[FONT_METRICS_ASCENT]; + maxAscent = (float) hires[FONT_METRICS_MAX_ASCENT]; + descent = (float) hires[FONT_METRICS_DESCENT]; + maxDescent = (float) hires[FONT_METRICS_MAX_DESCENT]; + maxAdvance = (float) hires[FONT_METRICS_MAX_ADVANCE]; + height = (float) hires[FONT_METRICS_HEIGHT]; + underlineOffset = (float) hires[FONT_METRICS_UNDERLINE_OFFSET]; + underlineThickness = (float) hires[FONT_METRICS_UNDERLINE_THICKNESS]; } /** @@ -261,26 +383,17 @@ public class GdkFontPeer extends ClasspathFontPeer return Font.ROMAN_BASELINE; } - private static class GdkFontLineMetrics extends LineMetrics + private class GdkFontLineMetrics extends LineMetrics { - private FontMetrics fm; - private int nchars; - private float strikethroughOffset, strikethroughThickness, - underlineOffset, underlineThickness; - - public GdkFontLineMetrics (GdkFontPeer fp, FontMetrics m, int n) + private int nchars; + public GdkFontLineMetrics (GdkFontPeer fp, int n) { - fm = m; nchars = n; - strikethroughOffset = 0f; - underlineOffset = 0f; - strikethroughThickness = ((float)fp.getSize(null)) / 12f; - underlineThickness = strikethroughThickness; } public float getAscent() { - return (float) fm.getAscent (); + return ascent; } public int getBaselineIndex() @@ -296,27 +409,52 @@ public class GdkFontPeer extends ClasspathFontPeer public float getDescent() { - return (float) fm.getDescent (); + return descent; } public float getHeight() { - return (float) fm.getHeight (); + return height; } - public float getLeading() { return 0.f; } - public int getNumChars() { return nchars; } - public float getStrikethroughOffset() { return 0.f; } - public float getStrikethroughThickness() { return 0.f; } - public float getUnderlineOffset() { return 0.f; } - public float getUnderlineThickness() { return 0.f; } + public float getLeading() + { + return height - (ascent + descent); + } + + public int getNumChars() + { + return nchars; + } + + public float getStrikethroughOffset() + { + // FreeType doesn't seem to provide a value here. + return ascent / 2; + } + + public float getStrikethroughThickness() + { + // FreeType doesn't seem to provide a value here. + return 1.f; + } + + public float getUnderlineOffset() + { + return underlineOffset; + } + + public float getUnderlineThickness() + { + return underlineThickness; + } } public LineMetrics getLineMetrics (Font font, CharacterIterator ci, int begin, int limit, FontRenderContext rc) { - return new GdkFontLineMetrics (this, getFontMetrics (font), limit - begin); + return new GdkFontLineMetrics (this, limit - begin); } public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc) @@ -361,14 +499,14 @@ public class GdkFontPeer extends ClasspathFontPeer public LineMetrics getLineMetrics (Font font, String str, FontRenderContext frc) { - return new GdkFontLineMetrics (this, getFontMetrics (font), str.length ()); + return new GdkFontLineMetrics (this, str.length ()); } public FontMetrics getFontMetrics (Font font) { - // Get the font metrics through GtkToolkit to take advantage of - // the metrics cache. - return Toolkit.getDefaultToolkit().getFontMetrics (font); + if (metrics == null) + metrics = new GdkFontMetrics(font); + return metrics; } /** @@ -387,4 +525,5 @@ public class GdkFontPeer extends ClasspathFontPeer { metricsCache.put( new Integer( glyphCode ), metrics ); } + } diff --git a/gnu/java/awt/peer/gtk/GtkToolkit.java b/gnu/java/awt/peer/gtk/GtkToolkit.java index d2721b43f..81367d6b0 100644 --- a/gnu/java/awt/peer/gtk/GtkToolkit.java +++ b/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -115,7 +115,6 @@ import java.awt.peer.WindowPeer; import java.io.InputStream; import java.net.URL; import java.util.HashMap; -import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; @@ -295,7 +294,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit "SansSerif" }); } - private class LRUCache extends LinkedHashMap + static class LRUCache extends LinkedHashMap { int max_entries; public LRUCache(int max) @@ -310,23 +309,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit } private LRUCache fontCache = new LRUCache(50); - private LRUCache metricsCache = new LRUCache(50); private LRUCache imageCache = new LRUCache(50); public FontMetrics getFontMetrics (Font font) { - synchronized (metricsCache) - { - if (metricsCache.containsKey(font)) - return (FontMetrics) metricsCache.get(font); - } - - FontMetrics m = new GdkFontMetrics (font); - synchronized (metricsCache) - { - metricsCache.put(font, m); - } - return m; + return ((GdkFontPeer) font.getPeer()).getFontMetrics(font); } public Image getImage (String filename) -- cgit v1.2.1