Hi,

I recently ran into a problem with using fractional font metrics with OpenJDK. The attached code (FractionalTextMetricsBug.java) reproduces the problem and the attached image shows the result on OpenJDK6 (which is the same as the result on OpenJDK7).

I believe this problem was introduced with the fix for 6697721 [1] as I observed this behaviour with OpenJDK6 after that particular fix was backported. The value of advh is based on ftglyph->linearHoriAdvance, which is the advance for the unhinted glyph [2]. If the glyph is hinted (which is often the case), ftglyph->metrics.horiAdvance gives a better value.

The attached patch is one attempt at fixing the problem. I am not sure if TEXT_AA_OFF (the antialiasing mode) is related to hinting - even though the comments in freetypescaler say that it is. With the patch, my test case works, and the text is rendered correctly with antialising set to either VALUE_TEXT_ANTIALIAS_ON, VALUE_TEXT_ANTIALIAS_OFF or VALUE_TEXT_ANTIALIAS_LCD_HRGB.

Thanks,
Omair

[1] http://hg.openjdk.java.net/jdk7/2d/jdk/rev/4092c04aeae7
[2] http://freetype.sourceforge.net/freetype2/docs/reference/ft2-base_interface.html#FT_GlyphSlotRec

<<attachment: openjdk-fractional-metrics-advance-bug.png>>

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class FractionalTextMetricsBug {

    public static void main(String[] args) throws Exception {

        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Anti aliasing rendering test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                Canvas drawingArea = new Canvas() {

                    /**
                     * 
                     */
                    private static final long serialVersionUID = 
-2281399219700950363L;

                    @Override
                    public void paint(Graphics _g) {
                        Graphics2D g = (Graphics2D) _g;
                        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                         
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                         RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                        g.drawString("Graphics2D Rendered Text", 5, 15);
                    }
                };
                drawingArea.setSize(new Dimension(300, 50));
                frame.getContentPane().add(drawingArea);

                frame.pack();
                frame.setVisible(true);

            }
        });
    }
}
diff -r 882103f334bb src/share/native/sun/font/freetypeScaler.c
--- a/src/share/native/sun/font/freetypeScaler.c	Thu Aug 19 15:13:12 2010 -0700
+++ b/src/share/native/sun/font/freetypeScaler.c	Tue Aug 31 14:15:57 2010 -0400
@@ -797,7 +797,12 @@
     }
 
     if (context->fmType == TEXT_FM_ON) {
-        double advh = FTFixedToFloat(ftglyph->linearHoriAdvance);
+        double advh;
+        if (context->aaType == TEXT_AA_OFF) {
+            advh = FTFixedToFloat(ftglyph->linearHoriAdvance);
+        } else {
+            advh = FT26Dot6ToFloat(ftglyph->metrics.horiAdvance);
+        }
         glyphInfo->advanceX =
             (float) (advh * FTFixedToFloat(context->transform.xx));
         glyphInfo->advanceY =

Reply via email to