Hi,
I committed this patch to HEAD. The font metrics we were returning were
larger than the ones Sun returns. This caused problems for applets that
rely on font metrics for positioning text correctly. With this patch we
now approximate Sun's metrics within a two pixel tolerance. I added
gnu.testlet.java.awt.FontMetrics.TestLogicalFontMetrics to show this.
Before this patch, it had 1484 failures. After the patch it has 118
failures (caused by Monospaced fonts). I'll fix these failures in a
separate patch.
Tom
2006-03-16 Thomas Fitzsimmons <[EMAIL PROTECTED]>
* gnu/java/awt/peer/gtk/GdkFontMetrics.java (getLeading): Always
return 0.
* gnu/java/awt/peer/gtk/GdkFontPeer.java (getFontMetrics): Get
font metrics through toolkit.
* gnu/java/awt/peer/gtk/GdkGraphics.java (getFontMetrics):
Likewise.
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c
(getFontMetrics): To calculate Java logical ascent and descent
values, average Pango ink and logical values.
Index: gnu/java/awt/peer/gtk/GdkFontMetrics.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkFontMetrics.java,v
retrieving revision 1.15
diff -u -r1.15 GdkFontMetrics.java
--- gnu/java/awt/peer/gtk/GdkFontMetrics.java 30 Sep 2005 09:58:31 -0000 1.15
+++ gnu/java/awt/peer/gtk/GdkFontMetrics.java 16 Mar 2006 20:19:08 -0000
@@ -110,14 +110,10 @@
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;
+ // Sun always returns 0.
+ return 0;
}
public int getAscent ()
Index: gnu/java/awt/peer/gtk/GdkFontPeer.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java,v
retrieving revision 1.7
diff -u -r1.7 GdkFontPeer.java
--- gnu/java/awt/peer/gtk/GdkFontPeer.java 2 Jul 2005 20:32:11 -0000 1.7
+++ gnu/java/awt/peer/gtk/GdkFontPeer.java 16 Mar 2006 20:19:08 -0000
@@ -43,6 +43,7 @@
import java.awt.Font;
import java.awt.FontMetrics;
+import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.LineMetrics;
@@ -301,7 +302,9 @@
public FontMetrics getFontMetrics (Font font)
{
- return new GdkFontMetrics (font);
+ // Get the font metrics through GtkToolkit to take advantage of
+ // the metrics cache.
+ return Toolkit.getDefaultToolkit().getFontMetrics (font);
}
}
Index: gnu/java/awt/peer/gtk/GdkGraphics.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java,v
retrieving revision 1.53
diff -u -r1.53 GdkGraphics.java
--- gnu/java/awt/peer/gtk/GdkGraphics.java 14 Dec 2005 21:33:38 -0000 1.53
+++ gnu/java/awt/peer/gtk/GdkGraphics.java 16 Mar 2006 20:19:08 -0000
@@ -48,6 +48,7 @@
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
+import java.awt.Toolkit;
import java.awt.image.ImageObserver;
import java.text.AttributedCharacterIterator;
@@ -373,7 +374,9 @@
public FontMetrics getFontMetrics (Font font)
{
- return new GdkFontMetrics (font);
+ // Get the font metrics through GtkToolkit to take advantage of
+ // the metrics cache.
+ return Toolkit.getDefaultToolkit().getFontMetrics (font);
}
native void setClipRectangle (int x, int y, int width, int height);
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c
===================================================================
RCS file: /sources/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c,v
retrieving revision 1.12
diff -u -r1.12 gnu_java_awt_peer_gtk_GdkFontPeer.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c 18 Nov 2005 21:05:06 -0000 1.12
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c 16 Mar 2006 20:19:08 -0000
@@ -239,6 +239,17 @@
struct peerfont *pfont = NULL;
jdouble *native_metrics = NULL;
PangoFontMetrics *pango_metrics = NULL;
+ PangoLayout* layout = NULL;
+ PangoRectangle ink_rect;
+ PangoRectangle logical_rect;
+ PangoLayoutIter* iter = NULL;
+ int pango_ascent = 0;
+ int pango_descent = 0;
+ int pango_ink_ascent = 0;
+ int pango_ink_descent = 0;
+ int baseline = 0;
+ int java_ascent = 0;
+ int java_descent = 0;
gdk_threads_enter();
@@ -254,21 +265,46 @@
g_assert (native_metrics != NULL);
- native_metrics[FONT_METRICS_ASCENT]
- = PANGO_PIXELS (pango_font_metrics_get_ascent (pango_metrics));
+ pango_ascent = PANGO_PIXELS (pango_font_metrics_get_ascent (pango_metrics));
+ pango_descent = PANGO_PIXELS (pango_font_metrics_get_descent (pango_metrics));
- native_metrics[FONT_METRICS_MAX_ASCENT]
- = native_metrics[FONT_METRICS_ASCENT];
+ layout = pango_layout_new (pfont->ctx);
- native_metrics[FONT_METRICS_DESCENT]
- = PANGO_PIXELS (pango_font_metrics_get_descent (pango_metrics));
+ /* Pango seems to produce ascent and descent values larger than
+ those that Sun produces for the same-sized font. It turns out
+ that an average of the "ink ascent" and "logical ascent" closely
+ approximates Sun's ascent values. Likewise for descent values.
+ This is expensive but we cache GdkFontMetrics so this should only
+ run once per Font instance. */
+ pango_layout_set_text (layout, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL"
+ "MNOPQRSTUVWXYZ0123456789", -1);
+ pango_layout_set_font_description (layout, pfont->desc);
- if (native_metrics[FONT_METRICS_DESCENT] < 0)
- native_metrics[FONT_METRICS_DESCENT]
- = - native_metrics[FONT_METRICS_DESCENT];
+ pango_layout_get_pixel_extents (layout, &ink_rect, &logical_rect);
- native_metrics[FONT_METRICS_MAX_DESCENT]
- = native_metrics[FONT_METRICS_DESCENT];
+ iter = pango_layout_get_iter (layout);
+
+ baseline = PANGO_PIXELS (pango_layout_iter_get_baseline (iter));
+
+ pango_ink_ascent = baseline - ink_rect.y;
+ pango_ink_descent = ink_rect.y + ink_rect.height - baseline;
+
+ java_ascent = (pango_ascent + pango_ink_ascent) >> 1;
+ java_descent = (pango_descent + pango_ink_descent) >> 1;
+
+ java_ascent = MAX(0, java_ascent);
+ java_descent = MAX(0, java_descent);
+
+ pango_ascent = MAX(0, pango_ascent);
+ pango_descent = MAX(0, pango_descent);
+
+ native_metrics[FONT_METRICS_ASCENT] = java_ascent;
+
+ native_metrics[FONT_METRICS_MAX_ASCENT] = pango_ascent;
+
+ native_metrics[FONT_METRICS_DESCENT] = java_descent;
+
+ native_metrics[FONT_METRICS_MAX_DESCENT] = pango_descent;
native_metrics[FONT_METRICS_MAX_ADVANCE]
= PANGO_PIXELS (pango_font_metrics_get_approximate_char_width